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
265 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}"
266 thread_ptr_str
= str("{0: <#020x}".format(thread
))
267 if int(thread
.static_param
) :
268 thread_ptr_str
+="[WQ]"
269 thread_id
= hex(thread
.thread_id
)
271 processor
= hex(thread
.last_processor
)
272 base_priority
= str(int(thread
.base_pri
))
273 sched_priority
= str(int(thread
.sched_pri
))
275 mode
= str(thread
.sched_mode
)
276 if "TIMESHARE" in mode
:
277 sched_mode
+="timeshare"
278 elif "FIXED" in mode
:
280 elif "REALTIME" in mode
:
281 sched_mode
+="realtime"
283 if (unsigned(thread
.bound_processor
) != 0):
287 if (unsigned(thread
.sched_flags
) & 0x0004):
291 if int(thread
.uthread
) != 0:
292 uthread
= Cast(thread
.uthread
, 'uthread *')
293 #check for thread name
294 if int(uthread
.pth_name
) != 0 :
295 th_name_strval
= Cast(uthread
.pth_name
, 'char *')
296 if len(str(th_name_strval
)) > 0 :
297 thread_name
= str(th_name_strval
)
299 #check for io_policy flags
300 if int(uthread
.uu_flag
) & 0x400:
301 io_policy_str
+='RAGE '
303 #now flags for task_policy
307 if int(thread
.effective_policy
.thep_darwinbg
) != 0:
309 if int(thread
.effective_policy
.thep_io_tier
) != 0:
311 if int(thread
.effective_policy
.thep_io_passive
) != 0:
313 if int(thread
.effective_policy
.thep_terminated
) != 0:
316 state
= int(thread
.state
)
317 thread_state_chars
= {0x0:'', 0x1:'W', 0x2:'S', 0x4:'R', 0x8:'U', 0x10:'H', 0x20:'A', 0x40:'P', 0x80:'I'}
321 state_str
+= thread_state_chars
[int(state
& mask
)]
324 if int(thread
.inspection
):
327 ast
= int(thread
.ast
) |
int(thread
.reason
)
328 ast_str
= GetASTSummary(ast
)
330 #wait queue information
334 if ( state
& 0x1 ) != 0:
335 #we need to look at the waitqueue as well
336 wait_queue_str
= str("{0: <#020x}".format(int(hex(thread
.waitq
), 16)))
337 wait_event_str
= str("{0: <#020x}".format(int(hex(thread
.wait_event
), 16)))
338 wait_event_str_sym
= kern
.Symbolicate(int(hex(thread
.wait_event
), 16))
339 if len(wait_event_str_sym
) > 0:
340 wait_event_str
= wait_event_str
.strip() + " <" + wait_event_str_sym
+ ">"
341 if int(thread
.uthread
) != 0 :
342 uthread
= Cast(thread
.uthread
, 'uthread *')
343 if int(uthread
.uu_wmesg
) != 0:
344 wait_message
= str(Cast(uthread
.uu_wmesg
, 'char *'))
346 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
)
350 def GetTaskRoleString(role
):
352 0 : "TASK_UNSPECIFIED",
353 1 : "TASK_FOREGROUND_APPLICATION",
354 2 : "TASK_BACKGROUND_APPLICATION",
355 3 : "TASK_CONTROL_APPLICATION",
356 4 : "TASK_GRAPHICS_SERVER",
357 5 : "TASK_THROTTLE_APPLICATION",
358 6 : "TASK_NONUI_APPLICATION",
359 7 : "TASK_DEFAULT_APPLICATION",
361 return role_strs
[int(role
)]
363 def GetCoalitionFlagString(coal
):
365 if (coal
.privileged
):
366 flags
.append('privileged')
367 if (coal
.termrequested
):
368 flags
.append('termrequested')
369 if (coal
.terminated
):
370 flags
.append('terminated')
372 flags
.append('reaped')
374 flags
.append('notified')
375 return "|".join(flags
)
377 def GetCoalitionTasks(queue
, coal_type
, thread_details
=False):
379 0x0 : "SFI_CLASS_UNSPECIFIED",
380 0x1 : "SFI_CLASS_DARWIN_BG",
381 0x2 : "SFI_CLASS_APP_NAP",
382 0x3 : "SFI_CLASS_MANAGED_FOCAL",
383 0x4 : "SFI_CLASS_MANAGED_NONFOCAL",
384 0x5 : "SFI_CLASS_DEFAULT_FOCAL",
385 0x6 : "SFI_CLASS_DEFAULT_NONFOCAL",
386 0x7 : "SFI_CLASS_KERNEL",
387 0x8 : "SFI_CLASS_OPTED_OUT",
388 0x9 : "SFI_CLASS_UTILITY",
389 0xA : "SFI_CLASS_LEGACY_FOCAL",
390 0xB : "SFI_CLASS_LEGACY_NONFOCAL",
391 0xC : "SFI_CLASS_USER_INITIATED_FOCAL",
392 0xD : "SFI_CLASS_USER_INITIATED_NONFOCAL",
393 0xE : "SFI_CLASS_USER_INTERACTIVE_FOCAL",
394 0xF : "SFI_CLASS_USER_INTERACTIVE_NONFOCAL",
395 0x10 : "SFI_CLASS_MAINTENANCE",
398 field_name
= 'task_coalition'
399 for task
in IterateLinkageChain(queue
, 'task *', field_name
, coal_type
* sizeof('queue_chain_t')):
400 task_str
= "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(task
),task
,GetProcNameForTask(task
),GetTaskRoleString(task
.effective_policy
.tep_role
))
402 for thread
in IterateQueue(task
.threads
, "thread_t", "task_threads"):
403 task_str
+= "\n\t\t\t|-> thread:" + hex(thread
) + ", " + sfi_strs
[int(thread
.sfi_class
)]
404 tasks
.append(task_str
)
407 def GetCoalitionTypeString(type):
408 """ Convert a coalition type field into a string
409 Currently supported types (from <mach/coalition.h>):
410 COALITION_TYPE_RESOURCE
411 COALITION_TYPE_JETSAM
413 if type == 0: # COALITION_TYPE_RESOURCE
419 def GetResourceCoalitionSummary(coal
, verbose
=False):
420 """ Summarize a resource coalition
422 out_string
= "Resource Coalition:\n\t Ledger:\n"
423 thread_details
= False
424 if config
['verbosity'] > vSCRIPT
:
425 thread_details
= True
426 ledgerp
= coal
.r
.ledger
427 if verbose
and unsigned(ledgerp
) != 0:
429 while i
!= ledgerp
.l_template
.lt_cnt
:
431 out_string
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, ledgerp
.l_entries
[i
], i
)
433 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
)
434 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
)
435 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
)
436 out_string
+= "\n\t Tasks:\n\t\t"
437 tasks
= GetCoalitionTasks(addressof(coal
.r
.tasks
), 0, thread_details
)
438 out_string
+= "\n\t\t".join(tasks
)
441 def GetJetsamCoalitionSummary(coal
, verbose
=False):
442 out_string
= "Jetsam Coalition:"
443 thread_details
= False
444 if config
['verbosity'] > vSCRIPT
:
445 thread_details
= True
446 if unsigned(coal
.j
.leader
) == 0:
447 out_string
+= "\n\t NO Leader!"
449 out_string
+= "\n\t Leader:\n\t\t"
450 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
))
451 out_string
+= "\n\t Extensions:\n\t\t"
452 tasks
= GetCoalitionTasks(addressof(coal
.j
.extensions
), 1, thread_details
)
453 out_string
+= "\n\t\t".join(tasks
)
454 out_string
+= "\n\t XPC Services:\n\t\t"
455 tasks
= GetCoalitionTasks(addressof(coal
.j
.services
), 1, thread_details
)
456 out_string
+= "\n\t\t".join(tasks
)
457 out_string
+= "\n\t Other Tasks:\n\t\t"
458 tasks
= GetCoalitionTasks(addressof(coal
.j
.other
), 1, thread_details
)
459 out_string
+= "\n\t\t".join(tasks
)
462 @lldb_type_summary(['coalition_t', 'coalition *'])
463 @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"))
464 def GetCoalitionSummary(coal
):
465 if unsigned(coal
) == 0:
466 return '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'.format(0, "", -1, -1, -1, -1, -1, "")
468 format_string
= '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'
469 type_string
= GetCoalitionTypeString(coal
.type)
470 flag_string
= GetCoalitionFlagString(coal
)
471 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
)
474 def GetCoalitionInfo(coal
, verbose
=False):
475 """ returns a string describing a coalition, including details about the particular coalition type.
477 coal : value object representing a coalition in the kernel
479 str : A string describing the coalition.
481 if unsigned(coal
) == 0:
482 return "<null coalition>"
483 typestr
= GetCoalitionTypeString(coal
.type)
484 flagstr
= GetCoalitionFlagString(coal
)
486 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
)
487 if coal
.type == 0: # COALITION_TYPE_RESOURCE
488 out_string
+= GetResourceCoalitionSummary(coal
, verbose
)
489 elif coal
.type == 1: # COALITION_TYPE_JETSAM
490 out_string
+= GetJetsamCoalitionSummary(coal
, verbose
)
492 out_string
+= "Unknown Type"
496 # Macro: showcoalitioninfo
498 @lldb_command('showcoalitioninfo')
499 def ShowCoalitionInfo(cmd_args
=None, cmd_options
={}):
500 """ Display more detailed information about a coalition
501 Usage: showcoalitioninfo <address of coalition>
504 if config
['verbosity'] > vHUMAN
:
507 print "No arguments passed"
508 print ShowCoalitionInfo
.__doc
__
510 coal
= kern
.GetValueFromAddress(cmd_args
[0], 'coalition *')
512 print "unknown arguments:", str(cmd_args
)
514 print GetCoalitionInfo(coal
, verbose
)
516 # EndMacro: showcoalitioninfo
518 # Macro: showallcoalitions
520 @lldb_command('showallcoalitions')
521 def ShowAllCoalitions(cmd_args
=None):
522 """ Print a summary listing of all the coalitions
525 print GetCoalitionSummary
.header
526 for c
in kern
.coalitions
:
527 print GetCoalitionSummary(c
)
529 # EndMacro: showallcoalitions
531 # Macro: showtaskcoalitions
533 @lldb_command('showtaskcoalitions', 'F:')
534 def ShowTaskCoalitions(cmd_args
=None, cmd_options
={}):
538 if "-F" in cmd_options
:
539 task_list
= FindTasksByName(cmd_options
["-F"])
541 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
544 raise ArgumentError("No arguments passed")
546 if len(task_list
) > 0:
547 print GetCoalitionSummary
.header
548 for task
in task_list
:
549 print GetCoalitionSummary(task
.coalition
[0])
550 print GetCoalitionSummary(task
.coalition
[1])
552 # EndMacro: showtaskcoalitions
554 @lldb_type_summary(['proc', 'proc *'])
555 @header("{0: >6s} {1: ^20s} {2: >14s} {3: ^10s} {4: <20s}".format("pid", "process", "io_policy", "wq_state", "command"))
556 def GetProcSummary(proc
):
557 """ Summarize the process data.
559 proc : value - value representaitng a proc * in kernel
561 str - string summary of the process.
564 format_string
= "{0: >6d} {1: >#020x} {2: >14s} {3: >2d} {4: >2d} {5: >2d} {6: <20s}"
565 pval
= proc
.GetSBValue()
566 #code.interact(local=locals())
567 if str(pval
.GetType()) != str(gettype('proc *')) :
568 return "Unknown type " + str(pval
.GetType()) + " " + str(hex(proc
))
570 out_string
+= "Process " + hex(proc
) + " is not valid."
572 pid
= int(proc
.p_pid
)
573 proc_addr
= int(hex(proc
), 16)
575 if int(proc
.p_lflag
) & 0x400000 :
576 proc_rage_str
= "RAGE"
578 task
= Cast(proc
.task
, 'task *')
582 if int(task
.effective_policy
.tep_darwinbg
) != 0:
584 if int(task
.effective_policy
.tep_lowpri_cpu
) != 0:
587 if int(task
.effective_policy
.tep_io_tier
) != 0:
589 if int(task
.effective_policy
.tep_io_passive
) != 0:
591 if int(task
.effective_policy
.tep_terminated
) != 0:
594 if int(task
.effective_policy
.tep_latency_qos
) != 0:
596 if int(task
.effective_policy
.tep_sup_active
) != 0:
601 work_queue
= Cast(proc
.p_wqptr
, 'workqueue *')
602 if proc
.p_wqptr
!= 0 :
603 wq_num_threads
= int(work_queue
.wq_nthreads
)
604 wq_idle_threads
= int(work_queue
.wq_thidlecount
)
605 wq_req_threads
= int(work_queue
.wq_reqcount
)
614 process_name
= str(proc
.p_comm
)
615 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
)
618 @lldb_type_summary(['tty_dev_t', 'tty_dev_t *'])
619 @header("{0: <20s} {1: <10s} {2: <10s} {3: <15s} {4: <15s} {5: <15s} {6: <15s}".format("tty_dev","master", "slave", "open", "free", "name", "revoke"))
620 def GetTTYDevSummary(tty_dev
):
621 """ Summarizes the important fields in tty_dev_t structure.
622 params: tty_dev: value - value object representing a tty_dev_t in kernel
623 returns: str - summary of the tty_dev
626 format_string
= "{0: <#020x} {1: <#010x} {2: <#010x} {3: <15s} {4: <15s} {5: <15s} {6: <15s}"
627 open_fn
= kern
.Symbolicate(int(hex(tty_dev
.open), 16))
628 free_fn
= kern
.Symbolicate(int(hex(tty_dev
.free
), 16))
629 name_fn
= kern
.Symbolicate(int(hex(tty_dev
.name
), 16))
630 revoke_fn
= kern
.Symbolicate(int(hex(tty_dev
.revoke
), 16))
631 out_string
+= format_string
.format(tty_dev
, tty_dev
.master
, tty_dev
.slave
, open_fn
, free_fn
, name_fn
, revoke_fn
)
634 @lldb_type_summary(['kqueue *'])
635 @header("{: <20s} {: <20s} {: <6s} {: <20s} {: <10s}".format('kqueue', 'process', '#events', 'wqs', 'state'))
636 def GetKQueueSummary(kq
):
637 """ summarizes kqueue information
638 returns: str - summary of kqueue
641 format_string
= "{o: <#020x} {o.kq_p: <#020x} {o.kq_count: <6d} {wqs: <#020x} {st_str: <10s}"
642 state
= int(kq
.kq_state
)
646 if int(state
& mask
):
647 state_str
+= ' ' + xnudefines
.kq_state_strings
[int(state
& mask
)]
649 out_string
+= format_string
.format(o
=kq
, wqs
=addressof(kq
.kq_wqs
), st_str
=state_str
)
650 out_string
+= "\n" + GetKnoteSummary
.header
651 for kn
in IterateTAILQ_HEAD(kq
.kq_head
, 'kn_tqe'):
652 out_string
+= "\n" + GetKnoteSummary(kn
)
655 @lldb_type_summary(['knote *'])
656 @header("{0: <20s} {1: <10s} {2: <10s} {3: <20s} {4: <20s} {5: <30s}".format('knote', 'ident', 'kev_flags', 'kn_kq', 'filtops', ' status'))
657 def GetKnoteSummary(kn
):
658 """ Summarizes a knote and related information
659 returns: str - summary of knote
662 format_string
= "{o: <#020x} {o.kn_kevent.ident: <#010X} {o.kn_kevent.flags: <#010X} {o.kn_kq: <#020X} {ops_str: <20s} {st_str: <30s}"
663 state
= unsigned(kn
.kn_status
)
664 fops_str
= kern
.Symbolicate(unsigned(kn
.kn_fop
))
669 status_desc
+= ' ' + xnudefines
.kn_state_strings
[int(state
& mask
)]
672 out_string
+= format_string
.format(o
=kn
, st_str
=status_desc
, ops_str
=fops_str
)
677 @lldb_command('showtask', 'F:')
678 def ShowTask(cmd_args
=None, cmd_options
={}):
679 """ Routine to print a summary listing of given task
680 Usage: showtask <address of task>
681 or : showtask -F <name of task>
684 if "-F" in cmd_options
:
685 task_list
= FindTasksByName(cmd_options
['-F'])
688 raise ArgumentError("Invalid arguments passed.")
690 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
692 raise ("Unknown arguments: %r" % cmd_args
)
693 task_list
.append(tval
)
695 for tval
in task_list
:
696 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
697 pval
= Cast(tval
.bsd_info
, 'proc *')
698 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
704 @lldb_command('showpid')
705 def ShowPid(cmd_args
=None):
706 """ Routine to print a summary listing of task corresponding to given pid
707 Usage: showpid <pid value>
710 print "No arguments passed"
711 print ShowPid
.__doc
__
713 pidval
= ArgumentStringToInt(cmd_args
[0])
715 pval
= Cast(t
.bsd_info
, 'proc *')
716 if pval
and pval
.p_pid
== pidval
:
717 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
718 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
725 @lldb_command('showproc')
726 def ShowProc(cmd_args
=None):
727 """ Routine to print a summary listing of task corresponding to given proc
728 Usage: showproc <address of proc>
731 print "No arguments passed"
732 print ShowProc
.__doc
__
734 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
736 print "unknown arguments:", str(cmd_args
)
738 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
739 tval
= Cast(pval
.task
, 'task *')
740 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
744 # Macro: showprocinfo
746 @lldb_command('showprocinfo')
747 def ShowProcInfo(cmd_args
=None):
748 """ Routine to display name, pid, parent & task for the given proc address
749 It also shows the Cred, Flags and state of the process
750 Usage: showprocinfo <address of proc>
753 print "No arguments passed"
754 print ShowProcInfo
.__doc
__
756 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
758 print "unknown arguments:", str(cmd_args
)
760 print GetProcInfo(pval
)
762 # EndMacro: showprocinfo
764 #Macro: showprocfiles
766 @lldb_command('showprocfiles')
767 def ShowProcFiles(cmd_args
=None):
768 """ Given a proc_t pointer, display the list of open file descriptors for the referenced process.
769 Usage: showprocfiles <proc_t>
772 print ShowProcFiles
.__doc
__
774 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc_t')
775 proc_filedesc
= proc
.p_fd
776 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
777 proc_ofiles
= proc_filedesc
.fd_ofiles
778 if unsigned(proc_ofiles
) == 0:
779 print 'No open files for proc {0: <s}'.format(cmd_args
[0])
781 print "{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO')
782 print "{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("")
796 while count
<= proc_lastfile
:
797 if unsigned(proc_ofiles
[count
]) != 0:
799 proc_fd_flags
= proc_ofiles
[count
].f_flags
800 proc_fd_fglob
= proc_ofiles
[count
].f_fglob
801 out_str
+= "{0: <5d} ".format(count
)
802 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
))
803 out_str
+= "0x{0:0>8x} ".format(unsigned(proc_fd_flags
))
804 proc_fd_ftype
= unsigned(proc_fd_fglob
.fg_ops
.fo_type
)
805 if proc_fd_ftype
in filetype_dict
:
806 out_str
+= "{0: <8s} ".format(filetype_dict
[proc_fd_ftype
])
808 out_str
+= "?: {0: <5d} ".format(proc_fd_ftype
)
809 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
.fg_data
))
810 if proc_fd_ftype
== 1:
811 fd_name
= Cast(proc_fd_fglob
.fg_data
, 'struct vnode *').v_name
812 out_str
+= "{0: <64s}".format(fd_name
)
817 #EndMacro: showprocfiles
820 def GetProcKqueues(proc
):
823 proc_filedesc
= proc
.p_fd
824 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
825 proc_ofiles
= proc_filedesc
.fd_ofiles
829 if unsigned(proc_ofiles
) == 0:
834 while count
<= proc_lastfile
:
835 if unsigned(proc_ofiles
[count
]) != 0:
836 proc_fd_flags
= proc_ofiles
[count
].f_flags
837 proc_fd_fglob
= proc_ofiles
[count
].f_fglob
838 proc_fd_ftype
= unsigned(proc_fd_fglob
.fg_ops
.fo_type
)
839 if proc_fd_ftype
== filetype_KQUEUE
:
840 q
= Cast(proc_fd_fglob
.fg_data
, 'struct kqueue *')
848 if unsigned(t
.bsd_info
) == 0:
850 pval
= Cast(t
.bsd_info
, 'proc *')
851 for kq
in GetProcKqueues(pval
):
854 #Macro: showallkqueues
855 @lldb_command('showallkqueues' ,'')
856 def ShowAllKqueues(cmd_args
=[], cmd_options
={}):
857 """ Display a summary of all the kqueues in the system """
858 for kq
in GetAllKqueues():
859 print GetKQueueSummary
.header
860 print GetKQueueSummary(kq
)
862 #EndMacro: showallkqueues
865 @lldb_command('showkqueue' ,'')
866 def ShowKQueue(cmd_args
=[], cmd_options
={}):
867 """ Given a struct kqueue pointer, display the summary of the kqueue
868 Usage: (lldb) showkqueue <struct kqueue *>
871 raise ArgumentError('Invalid arguments')
873 kq
= kern
.GetValueFromAddress(cmd_args
[0], 'struct kqueue *')
874 print GetKQueueSummary
.header
875 print GetKQueueSummary(kq
)
877 #EndMacro: showkqueue
881 @lldb_command('showtty')
882 def ShowTTY(cmd_args
=None):
883 """ Display information about a struct tty
884 Usage: showtty <tty struct>
887 print ShowTTY
.__doc
__
890 tty
= kern
.GetValueFromAddress(cmd_args
[0], 'struct tty *')
891 print "TTY structure at: {0: <s}".format(cmd_args
[0])
892 print "Last input to raw queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_rawq
.c_cs
), tty
.t_rawq
.c_cs
)
893 print "Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_canq
.c_cs
), tty
.t_canq
.c_cs
)
894 print "Last output data: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_outq
.c_cs
), tty
.t_outq
.c_cs
)
896 ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'],
897 ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'],
898 ['', 'TS_BUSY (Draining output)'],
899 ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'],
900 ['', 'TS_FLUSH (Outq has been flushed during DMA)'],
901 ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'],
902 ['', 'TS_TBLOCK (Further input blocked)'],
903 ['', 'TS_TIMEOUT (Wait for output char processing)'],
904 ['', 'TS_TTSTOP (Output paused)'],
905 ['', 'TS_WOPEN (Open in progress)'],
906 ['', 'TS_XCLUDE (Tty requires exclusivity)'],
907 ['', 'TS_BKSL (State for lowercase \\ work)'],
908 ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'],
909 ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'],
910 ['', 'TS_LNCH (Next character is literal)'],
911 ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'],
912 ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'],
913 ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'],
914 ['', 'TS_SNOOP (Device is being snooped on)'],
915 ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'],
916 ['', 'TS_ZOMBIE (Connection lost)'],
917 ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'],
918 ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'],
919 ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)']
923 tty_state
= unsigned(tty
.t_state
)
926 if tty_state
& mask
!= 0:
927 if len(tty_state_info
[index
][1]) > 0:
928 print '\t' + tty_state_info
[index
][1]
930 if len(tty_state_info
[index
][0]) > 0:
931 print '\t' + tty_state_info
[index
][0]
934 print "Flags: 0x{0:0>8x}".format(unsigned(tty
.t_flags
))
935 print "Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty
.t_pgrp
))
936 print "Enclosing session: 0x{0:0>16x}".format(unsigned(tty
.t_session
))
938 print "\tInput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_iflag
))
939 print "\tOutput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_oflag
))
940 print "\tControl Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_cflag
))
941 print "\tLocal Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_lflag
))
942 print "\tInput Speed: {0: <8d}".format(tty
.t_termios
.c_ispeed
)
943 print "\tOutput Speed: {0: <8d}".format(tty
.t_termios
.c_ospeed
)
944 print "High Watermark: {0: <d} bytes".format(tty
.t_hiwat
)
945 print "Low Watermark : {0: <d} bytes".format(tty
.t_lowat
)
949 #Macro showallttydevs
951 @lldb_command('showallttydevs')
952 def ShowAllTTYDevs(cmd_args
=[], cmd_options
={}):
953 """ Show a list of ttydevs registered in the system.
957 tty_dev_head
= kern
.globals.tty_dev_head
958 tty_dev
= tty_dev_head
959 print GetTTYDevSummary
.header
960 while unsigned(tty_dev
) != 0:
961 print GetTTYDevSummary(tty_dev
)
962 tty_dev
= tty_dev
.next
965 #EndMacro: showallttydevs
967 #Macro: dumpthread_terminate_queue
969 @lldb_command('dumpthread_terminate_queue')
970 def DumpThreadTerminateQueue(cmd_args
=None):
971 """ Displays the contents of the specified call_entry queue.
972 Usage: dumpthread_terminate_queue
976 print GetThreadSummary
.header
977 for th
in IterateQueue(addressof(kern
.globals.thread_terminate_queue
), 'struct thread *', 'q_link'):
978 print GetThreadSummary(th
)
980 print "{0: <d} entries!".format(count
)
982 #EndMacro: dumpthread_terminate_queue
984 #Macro: dumpcrashed_thread_queue
986 @lldb_command('dumpcrashed_thread_queue')
987 def DumpCrashedThreadsQueue(cmd_args
=None):
988 """ Displays the contents of the specified call_entry queue.
989 Usage: dumpcrashed_thread_queue
993 print GetThreadSummary
.header
994 for th
in IterateQueue(addressof(kern
.globals.crashed_threads_queue
), 'struct thread *', 'q_link'):
995 print GetThreadSummary(th
)
997 print "{0: <d} entries!".format(count
)
999 #EndMacro: dumpcrashed_thread_queue
1001 #Macro: dumpcallqueue
1003 @lldb_command('dumpcallqueue')
1004 def DumpCallQueue(cmd_args
=None):
1005 """ Displays the contents of the specified call_entry queue.
1006 Usage: dumpcallqueue <queue_head_t *>
1009 raise ArgumentError("Invalid arguments")
1011 print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC')
1012 callhead
= kern
.GetValueFromAddress(cmd_args
[0], 'queue_head_t *')
1014 for callentry
in IterateQueue(callhead
, 'struct call_entry *', 'q_link'):
1015 print "{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format(
1016 unsigned(callentry
), unsigned(callentry
.param0
), unsigned(callentry
.param1
),
1017 unsigned(callentry
.deadline
), unsigned(callentry
.func
))
1019 print "{0: <d} entries!".format(count
)
1021 #EndMacro: dumpcallqueue
1023 @lldb_command('showalltasklogicalwrites')
1024 def ShowAllTaskIOStats(cmd_args
=None):
1025 """ Commad to print I/O stats for all tasks
1027 print "{0: <20s} {1: <20s} {2: <20s} {3: <20s} {4: <20s} {5: <20s}".format("task", "Immediate Writes", "Deferred Writes", "Invalidated Writes", "Metadata Writes", "name")
1028 for t
in kern
.tasks
:
1029 pval
= Cast(t
.bsd_info
, 'proc *')
1030 print "{0: <#18x} {1: >20d} {2: >20d} {3: >20d} {4: >20d} {5: <20s}".format(t
,
1031 t
.task_immediate_writes
,
1032 t
.task_deferred_writes
,
1033 t
.task_invalidated_writes
,
1034 t
.task_metadata_writes
,
1038 @lldb_command('showalltasks','C')
1039 def ShowAllTasks(cmd_args
=None, cmd_options
={}):
1040 """ Routine to print a summary listing of all the tasks
1041 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1042 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1043 io_policy -> RAGE - rapid aging of vnodes requested
1044 NORM - normal I/O explicitly requested (this is the default)
1045 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1046 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1047 Usage: (lldb) showalltasks -C : describe the corpse structure
1052 if '-C' in cmd_options
:
1054 extra_hdr
+= " " + GetKCDataSummary
.header
1056 print GetTaskSummary
.header
+ extra_hdr
+ " " + GetProcSummary
.header
1057 for t
in kern
.tasks
:
1058 pval
= Cast(t
.bsd_info
, 'proc *')
1059 out_str
= GetTaskSummary(t
, showcorpse
) + " " + GetProcSummary(pval
)
1063 @lldb_command('showterminatedtasks')
1064 def ShowTerminatedTasks(cmd_args
=None):
1065 """ Routine to print a summary listing of all the terminated tasks
1066 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1067 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1068 io_policy -> RAGE - rapid aging of vnodes requested
1069 NORM - normal I/O explicitly requested (this is the default)
1070 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1071 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1072 syntax: (lldb)showallterminatedtasks
1075 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1076 for t
in kern
.terminated_tasks
:
1077 pval
= Cast(t
.bsd_info
, 'proc *')
1078 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1081 # Macro: showtaskstacks
1083 def ShowTaskStacks(task
):
1084 """ Print a task with summary and stack information for each of its threads
1087 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1088 pval
= Cast(task
.bsd_info
, 'proc *')
1089 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1090 for th
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1091 print " " + GetThreadSummary
.header
1092 print " " + GetThreadSummary(th
)
1093 print GetThreadBackTrace(th
, prefix
=" ") + "\n"
1095 def FindTasksByName(searchstr
, ignore_case
=True):
1096 """ Search the list of tasks by name.
1098 searchstr: str - a regex like string to search for task
1099 ignore_case: bool - If False then exact matching will be enforced
1101 [] - array of task object. Empty if not found any
1105 re_options
= re
.IGNORECASE
1106 search_regex
= re
.compile(searchstr
, re_options
)
1108 for t
in kern
.tasks
:
1109 pval
= Cast(t
.bsd_info
, "proc *")
1110 process_name
= "{:s}".format(pval
.p_comm
)
1111 if search_regex
.search(process_name
):
1115 @lldb_command('showtaskstacks', 'F:')
1116 def ShowTaskStacksCmdHelper(cmd_args
=None, cmd_options
={}):
1117 """ Routine to print out the stack for each thread in a task
1118 Usage: showtaskstacks <0xaddress of task>
1119 or: showtaskstacks -F launchd
1122 if "-F" in cmd_options
:
1123 find_task_str
= cmd_options
["-F"]
1124 task_list
= FindTasksByName(find_task_str
)
1125 for tval
in task_list
:
1126 ShowTaskStacks(tval
)
1130 raise ArgumentError("No arguments passed")
1132 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1134 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
1136 ShowTaskStacks(tval
)
1139 # EndMacro: showtaskstacks
1141 def CheckTaskProcRefs(task
, proc
):
1142 for thread
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1143 if int(thread
.uthread
) == 0:
1145 uthread
= Cast(thread
.uthread
, 'uthread *')
1146 refcount
= int(uthread
.uu_proc_refcount
)
1147 uu_ref_index
= int(uthread
.uu_pindex
)
1150 for ref
in range(0, uu_ref_index
):
1151 if unsigned(uthread
.uu_proc_ps
[ref
]) == unsigned(proc
):
1152 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1153 pval
= Cast(task
.bsd_info
, 'proc *')
1154 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1155 print "\t" + GetThreadSummary
.header
1156 print "\t" + GetThreadSummary(thread
) + "\n"
1158 for frame
in range (0, 10):
1159 trace_addr
= unsigned(uthread
.uu_proc_pcs
[ref
][frame
])
1160 symbol_arr
= kern
.SymbolicateFromAddress(unsigned(trace_addr
))
1162 symbol_str
= str(symbol_arr
[0].addr
)
1165 print '{0: <#x} {1: <s}'.format(trace_addr
, symbol_str
)
1168 @lldb_command('showprocrefs')
1169 def ShowProcRefs(cmd_args
= None):
1170 """ Display information on threads/BTs that could be holding a reference on the specified proc
1171 NOTE: We can't say affirmatively if any of these references are still held since
1172 there's no way to pair references with drop-refs in the current infrastructure.
1173 Usage: showprocrefs <proc>
1175 if cmd_args
== None or len(cmd_args
) < 1:
1176 raise ArgumentError("No arguments passed")
1178 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
1180 for t
in kern
.tasks
:
1181 CheckTaskProcRefs(t
, proc
)
1182 for t
in kern
.terminated_tasks
:
1183 CheckTaskProcRefs(t
, proc
)
1187 @lldb_command('showallthreads')
1188 def ShowAllThreads(cmd_args
= None):
1189 """ Display info about all threads in the system
1191 for t
in kern
.tasks
:
1192 ShowTaskThreads([str(int(t
))])
1195 for t
in kern
.terminated_tasks
:
1196 print "Terminated: \n"
1197 ShowTaskThreads([str(int(t
))])
1202 @lldb_command('showtaskthreads', "F:")
1203 def ShowTaskThreads(cmd_args
= None, cmd_options
={}):
1204 """ Display thread information for a given task
1205 Usage: showtaskthreads <0xaddress of task>
1206 or: showtaskthreads -F <name>
1209 if "-F" in cmd_options
:
1210 task_list
= FindTasksByName(cmd_options
["-F"])
1212 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1215 raise ArgumentError("No arguments passed")
1217 for task
in task_list
:
1218 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1219 pval
= Cast(task
.bsd_info
, 'proc *')
1220 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1221 print "\t" + GetThreadSummary
.header
1222 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1223 print "\t" + GetThreadSummary(thval
)
1226 @lldb_command('showact')
1227 def ShowAct(cmd_args
=None):
1228 """ Routine to print out the state of a specific thread.
1229 usage: showact <activation>
1231 if cmd_args
== None or len(cmd_args
) < 1:
1232 print "No arguments passed"
1233 print ShowAct
.__doc
__
1235 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1236 print GetThreadSummary
.header
1237 print GetThreadSummary(threadval
)
1239 @lldb_command('showactstack')
1240 def ShowActStack(cmd_args
=None):
1241 """ Routine to print out the stack of a specific thread.
1242 usage: showactstack <activation>
1244 if cmd_args
== None or len(cmd_args
) < 1:
1245 print "No arguments passed"
1246 print ShowAct
.__doc
__.strip()
1248 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1249 print GetThreadSummary
.header
1250 print GetThreadSummary(threadval
)
1251 print GetThreadBackTrace(threadval
, prefix
="\t")
1254 @lldb_command('switchtoact')
1255 def SwitchToAct(cmd_args
=None):
1256 """ Switch to different context specified by activation
1257 This command allows gdb to examine the execution context and call
1258 stack for the specified activation. For example, to view the backtrace
1259 for an activation issue "switchtoact <address>", followed by "bt".
1260 Before resuming execution, issue a "resetctx" command, to
1261 return to the original execution context.
1263 if cmd_args
== None or len(cmd_args
) < 1:
1264 print "No arguments passed"
1265 print SwitchToAct
.__doc
__.strip()
1267 thval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1268 lldbthread
= GetLLDBThreadForKernelThread(thval
)
1269 print GetThreadSummary
.header
1270 print GetThreadSummary(thval
)
1271 LazyTarget
.GetProcess().selected_thread
= lldbthread
1272 if not LazyTarget
.GetProcess().SetSelectedThread(lldbthread
):
1273 print "Failed to switch thread."
1276 @lldb_command('switchtoregs')
1277 def SwitchToRegs(cmd_args
=None):
1278 """ Routine to switch to a register state.
1279 Usage: (lldb) switchtoregs <struct arm_saved_state[64] *>
1280 This command creates a fake thread in lldb with the saved register state.
1281 Note: This command ONLY works for ARM based kernel setup.
1284 if cmd_args
== None or len(cmd_args
) < 1:
1285 raise ArgumentError("No arguments passed")
1287 lldb_process
= LazyTarget
.GetProcess()
1289 saved_state
= ArgumentStringToInt(cmd_args
[0])
1290 # any change to this logic requires change in operating_system.py as well
1291 fake_thread_id
= 0xdead0000 |
(saved_state
& ~
0xffff0000)
1292 fake_thread_id
= fake_thread_id
& 0xdeadffff
1293 lldb_process
.CreateOSPluginThread(0xdeadbeef, saved_state
)
1294 lldbthread
= lldb_process
.GetThreadByID(int(fake_thread_id
))
1296 if not lldbthread
.IsValid():
1297 print "Failed to create thread"
1300 lldb_process
.selected_thread
= lldbthread
1301 if not lldb_process
.SetSelectedThread(lldbthread
):
1302 print "Failed to switch thread"
1303 print "Switched to Fake thread created from register state at 0x%x" % saved_state
1307 # Macro: showallstacks
1308 @lldb_command('showallstacks')
1309 def ShowAllStacks(cmd_args
=None):
1310 """Routine to print out the stack for each thread in the system.
1312 for t
in kern
.tasks
:
1318 # EndMacro: showallstacks
1320 # Macro: showcurrentstacks
1321 @lldb_command('showcurrentstacks')
1322 def ShowCurrentStacks(cmd_args
=None):
1323 """ Routine to print out the thread running on each cpu (incl. its stack)
1325 processor_list
= kern
.GetGlobalVariable('processor_list')
1326 current_processor
= processor_list
1327 while unsigned(current_processor
) > 0:
1328 print "\n" + GetProcessorSummary(current_processor
)
1329 active_thread
= current_processor
.active_thread
1330 if unsigned(active_thread
) != 0 :
1331 task_val
= active_thread
.task
1332 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1333 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1334 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1335 print "\t" + GetThreadSummary
.header
1336 print "\t" + GetThreadSummary(active_thread
)
1337 print "\tBacktrace:"
1338 print GetThreadBackTrace(active_thread
, prefix
="\t")
1339 current_processor
= current_processor
.processor_list
1341 # EndMacro: showcurrentstacks
1343 @lldb_command('showcurrentthreads')
1344 def ShowCurrentThreads(cmd_args
=None):
1345 """ Display info about threads running on each cpu """
1346 processor_list
= kern
.GetGlobalVariable('processor_list')
1347 current_processor
= processor_list
1348 while unsigned(current_processor
) > 0:
1349 print GetProcessorSummary(current_processor
)
1350 active_thread
= current_processor
.active_thread
1351 if unsigned(active_thread
) != 0 :
1352 task_val
= active_thread
.task
1353 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1354 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1355 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1356 print "\t" + GetThreadSummary
.header
1357 print "\t" + GetThreadSummary(active_thread
)
1358 current_processor
= current_processor
.processor_list
1361 def GetFullBackTrace(frame_addr
, verbosity
= vHUMAN
, prefix
= ""):
1362 """ Get backtrace across interrupt context.
1363 params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7)
1364 prefix - str - prefix for each line of output.
1369 frame_ptr
= frame_addr
1370 previous_frame_ptr
= 0
1371 # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header
1372 mh_execute_addr
= int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16)
1373 while frame_ptr
and frame_ptr
!= previous_frame_ptr
and bt_count
< 128:
1374 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
):
1376 pc_val
= kern
.GetValueFromAddress(frame_ptr
+ kern
.ptrsize
,'uintptr_t *')
1377 pc_val
= unsigned(dereference(pc_val
))
1378 out_string
+= prefix
+ GetSourceInformationForAddress(pc_val
) + "\n"
1380 previous_frame_ptr
= frame_ptr
1381 frame_val
= kern
.GetValueFromAddress((frame_ptr
), 'uintptr_t *')
1382 if unsigned(frame_val
) == 0:
1384 frame_ptr
= unsigned(dereference(frame_val
))
1388 @lldb_command('fullbt')
1389 def FullBackTrace(cmd_args
=[]):
1390 """ Show full backtrace across the interrupt boundary.
1391 Syntax: fullbt <frame ptr>
1392 Example: fullbt `$rbp`
1394 if len(cmd_args
) < 1:
1395 print FullBackTrace
.__doc
__
1397 print GetFullBackTrace(ArgumentStringToInt(cmd_args
[0]), prefix
="\t")
1399 @lldb_command('fullbtall')
1400 def FullBackTraceAll(cmd_args
=[]):
1401 """ Show full backtrace across the interrupt boundary for threads running on all processors.
1405 for processor
in IterateLinkedList(kern
.globals.processor_list
, 'processor_list') :
1406 print "\n" + GetProcessorSummary(processor
)
1407 active_thread
= processor
.active_thread
1408 if unsigned(active_thread
) != 0 :
1409 task_val
= active_thread
.task
1410 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1411 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1412 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1413 print "\t" + GetThreadSummary
.header
1414 print "\t" + GetThreadSummary(active_thread
)
1415 print "\tBacktrace:"
1417 ThreadVal
= GetLLDBThreadForKernelThread(active_thread
)
1419 FramePtr
= ThreadVal
.frames
[0].GetFP()
1421 print GetFullBackTrace(unsigned(FramePtr
), prefix
="\t")
1424 @lldb_command('symbolicate')
1425 def SymbolicateAddress(cmd_args
=[]):
1426 """ Symbolicate an address for symbol information from loaded symbols
1427 Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr"
1429 if len(cmd_args
) < 1:
1430 print "Invalid address.\nSyntax: symbolicate <address>"
1432 print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args
[0]))
1435 @lldb_command('showinitchild')
1436 def ShowInitChild(cmd_args
=None):
1437 """ Routine to print out all processes in the system
1438 which are children of init process
1440 headp
= kern
.globals.initproc
.p_children
1441 for pp
in IterateListEntry(headp
, 'struct proc *', 'p_sibling'):
1442 print GetProcInfo(pp
)
1445 @lldb_command('showproctree')
1446 def ShowProcTree(cmd_args
=None):
1447 """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes.
1448 If no argument is given, showproctree will print all the processes in the system.
1449 If pid is specified, showproctree prints all the descendants of the indicated process
1453 search_pid
= ArgumentStringToInt(cmd_args
[0])
1456 print "pid specified must be a positive number"
1457 print ShowProcTree
.__doc
__
1460 hdr_format
= "{0: <6s} {1: <14s} {2: <9s}\n"
1461 out_string
= hdr_format
.format("PID", "PROCESS", "POINTER")
1462 out_string
+= hdr_format
.format('='*3, '='*7, '='*7)
1463 proc
= GetProcForPid(search_pid
)
1464 out_string
+= "{0: <6d} {1: <14s} [ {2: #019x} ]\n".format(proc
.p_ppid
, proc
.p_pptr
.p_comm
, unsigned(proc
.p_pptr
))
1465 out_string
+= "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(proc
.p_pid
, proc
.p_comm
, unsigned(proc
))
1467 ShowProcTreeRecurse(proc
, "| ")
1471 def ShowProcTreeRecurse(proc
, prefix
=""):
1472 """ Prints descendants of a given proc in hierarchial tree form
1474 proc : core.value representing a struct proc * in the kernel
1476 str : String containing info about a given proc and its descendants in tree form
1478 if proc
.p_childrencnt
> 0:
1479 head_ptr
= proc
.p_children
.lh_first
1481 for p
in IterateListEntry(proc
.p_children
, 'struct proc *', 'p_sibling'):
1482 print prefix
+ "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(p
.p_pid
, p
.p_comm
, unsigned(p
))
1483 ShowProcTreeRecurse(p
, prefix
+ "| ")
1485 @lldb_command('showthreadfortid')
1486 def ShowThreadForTid(cmd_args
=None):
1487 """ The thread structure contains a unique thread_id value for each thread.
1488 This command is used to retrieve the address of the thread structure(thread_t)
1489 corresponding to a given thread_id.
1492 print "Please provide thread_t whose tid you'd like to look up"
1493 print ShowThreadForTid
.__doc
__
1495 search_tid
= ArgumentStringToInt(cmd_args
[0])
1496 for taskp
in kern
.tasks
:
1497 for actp
in IterateQueue(taskp
.threads
, 'struct thread *', 'task_threads'):
1498 if search_tid
== int(actp
.thread_id
):
1499 print "Found {0: #019x}".format(actp
)
1500 print GetThreadSummary
.header
1501 print GetThreadSummary(actp
)
1503 print "Not a valid thread_id"
1505 def GetProcessorSummary(processor
):
1506 """ Internal function to print summary of processor
1507 params: processor - value representing struct processor *
1508 return: str - representing the details of given processor
1511 processor_state_str
= "INVALID"
1512 processor_state
= int(processor
.state
)
1514 processor_states
= {
1518 # 3 (formerly INACTIVE)
1524 if processor_state
in processor_states
:
1525 processor_state_str
= "{0: <11s} ".format(processor_states
[processor_state
])
1527 processor_recommended_str
= ""
1528 if int(processor
.is_recommended
) == 0:
1529 processor_recommended_str
= " (not recommended)"
1532 preemption_disable
= 0
1533 preemption_disable_str
= ""
1535 if kern
.arch
== 'x86_64':
1536 cpu_data
= kern
.globals.cpu_data_ptr
[processor
.cpu_id
]
1537 if (cpu_data
!= 0) :
1538 ast
= cpu_data
.cpu_pending_ast
1539 preemption_disable
= cpu_data
.cpu_preemption_level
1540 # On arm64, it's kern.globals.CpuDataEntries[processor.cpu_id].cpu_data_vaddr
1541 # but LLDB can't find CpuDataEntries...
1543 ast_str
= GetASTSummary(ast
)
1545 if (preemption_disable
!= 0) :
1546 preemption_disable_str
= "Preemption Disabled"
1548 out_str
= "Processor {: <#018x} cpu_id {:>#4x} AST: {:<6s} State {:<s}{:<s} {:<s}\n".format(
1549 processor
, int(processor
.cpu_id
), ast_str
, processor_state_str
, processor_recommended_str
,
1550 preemption_disable_str
)
1553 def GetLedgerEntrySummary(ledger_template
, ledger
, i
):
1554 """ Internal function to get internals of a ledger entry (*not* a ledger itself)
1555 params: ledger_template - value representing struct ledger_template_t for the task or thread
1556 ledger - value representing struct ledger_entry *
1557 return: str - formatted output information of ledger entries
1559 ledger_limit_infinity
= (uint64_t(0x1).value
<< 63) - 1
1560 lf_refill_scheduled
= 0x0400
1561 lf_tracking_max
= 0x4000
1564 now
= unsigned(kern
.globals.sched_tick
) / 20
1567 out_str
+= "{: >32s} {:<2d}:".format(ledger_template
.lt_entries
[i
].et_key
, i
)
1568 out_str
+= "{: >15d} ".format(unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
))
1569 if (ledger
.le_flags
& lf_tracking_max
):
1570 out_str
+= "{:9d} {:5d} ".format(ledger
._le
.le_peaks
[0].le_max
, now
- unsigned(ledger
._le
.le_peaks
[0].le_time
))
1571 out_str
+= "{:9d} {:4d} ".format(ledger
._le
.le_peaks
[1].le_max
, now
- unsigned(ledger
._le
.le_peaks
[1].le_time
))
1573 out_str
+= " - - - - "
1575 out_str
+= "{:12d} {:12d} ".format(unsigned(ledger
.le_credit
), unsigned(ledger
.le_debit
))
1576 if (unsigned(ledger
.le_limit
) != ledger_limit_infinity
):
1577 out_str
+= "{:12d} ".format(unsigned(ledger
.le_limit
))
1581 if (ledger
.le_flags
& lf_refill_scheduled
):
1582 out_str
+= "{:15d} ".format(ledger
._le
.le_refill
.le_refill_period
)
1586 if (ledger
.le_flags
& lf_refill_scheduled
):
1587 out_str
+= "{:9d} ".format((unsigned(ledger
.le_limit
) * 100) / ledger
._le
.le_refill
.le_refill_period
)
1591 if (unsigned(ledger
.le_warn_level
) != ledger_limit_infinity
):
1592 out_str
+= "{:9d} ".format((unsigned(ledger
.le_warn_level
) * 100) / unsigned(ledger
.le_limit
))
1596 if ((unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
)) > unsigned(ledger
.le_limit
)):
1601 out_str
+= "{:#8x}\n".format(ledger
.le_flags
)
1604 def GetThreadLedgerSummary(thread_val
):
1605 """ Internal function to get a summary of ledger entries for the given thread
1606 params: thread - value representing struct thread *
1607 return: str - formatted output information for ledger entries of the input thread
1609 out_str
= " [{:#08x}]\n".format(thread_val
)
1610 ledgerp
= thread_val
.t_threadledger
1613 while i
!= ledgerp
.l_template
.lt_cnt
:
1614 out_str
+= GetLedgerEntrySummary(kern
.globals.thread_ledger_template
,
1615 ledgerp
.l_entries
[i
], i
)
1619 @header("{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >9s} {5: >6s} {6: >8s} {7: <10s} {8: <9s} \
1620 {9: <12s} {10: <7s} {11: <15s} {12: <8s} {13: <9s} {14: <6s} {15: >6s}".format(
1621 "task [thread]", "entry", "#", "balance", "peakA", "(age)", "peakB", "(age)", "credit",
1622 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags"))
1623 def GetTaskLedgers(task_val
):
1624 """ Internal function to get summary of ledger entries from the task and its threads
1625 params: task_val - value representing struct task *
1626 return: str - formatted output information for ledger entries of the input task
1629 task_ledgerp
= task_val
.ledger
1631 out_str
+= "{: #08x} ".format(task_val
)
1632 pval
= Cast(task_val
.bsd_info
, 'proc *')
1634 out_str
+= "{: <5s}:\n".format(pval
.p_comm
)
1636 out_str
+= "Invalid process:\n"
1637 while i
!= task_ledgerp
.l_template
.lt_cnt
:
1638 out_str
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, task_ledgerp
.l_entries
[i
], i
)
1642 for thval
in IterateQueue(task_val
.threads
, 'thread *', 'task_threads'):
1643 out_str
+= GetThreadLedgerSummary(thval
)
1647 # Macro: showtaskledgers
1649 @lldb_command('showtaskledgers', 'F:')
1650 def ShowTaskLedgers(cmd_args
=None, cmd_options
={}):
1651 """ Routine to print a summary of ledger entries for the task and all of its threads
1652 Usage: showtaskledgers <address of task>
1653 or : showtaskledgers -F <name of task>
1655 if "-F" in cmd_options
:
1656 task_list
= FindTasksByName(cmd_options
["-F"])
1657 for tval
in task_list
:
1658 print GetTaskLedgers
.header
1659 print GetTaskLedgers(tval
)
1663 raise ArgumentError("No arguments passed.")
1664 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1666 raise ArgumentError("unknown arguments: %r" %cmd
_args
)
1667 print GetTaskLedgers
.header
1668 print GetTaskLedgers(tval
)
1670 # EndMacro: showtaskledgers
1672 # Macro: showalltaskledgers
1674 @lldb_command('showalltaskledgers')
1675 def ShowAllTaskLedgers(cmd_args
=None):
1676 """ Routine to print a summary of ledger entries for all tasks and respective threads
1677 Usage: showalltaskledgers
1679 for t
in kern
.tasks
:
1680 task_val
= unsigned(t
)
1681 ShowTaskLedgers([task_val
])
1683 # EndMacro: showalltaskledgers
1685 # Macro: showprocuuidpolicytable
1687 @lldb_type_summary(['proc_uuid_policy_entry'])
1688 @header("{0: <36s} {1: <10s}".format("uuid", "flags"))
1689 def GetProcUUIDPolicyEntrySummary(entry
):
1690 """ Summarizes the important fields in proc_uuid_policy_entry structure.
1691 params: entry: value - value object representing an entry
1692 returns: str - summary of the entry
1696 data
.append(int(entry
.uuid
[i
]))
1697 flags
= unsigned(entry
.flags
)
1698 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
)
1701 @lldb_command('showprocuuidpolicytable')
1702 def ShowProcUUIDPolicyTable(cmd_args
=None):
1703 """ Routine to print the proc UUID policy table
1704 Usage: showprocuuidpolicytable
1706 hashslots
= unsigned(kern
.globals.proc_uuid_policy_hash_mask
)
1707 print "{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary
.header
1708 for i
in range(0, hashslots
+1):
1709 headp
= addressof(kern
.globals.proc_uuid_policy_hashtbl
[i
])
1711 for entry
in IterateListEntry(headp
, 'struct proc_uuid_policy_entry *', 'entries'):
1712 print "{0: >2d}.{1: <5d} ".format(i
, entrynum
) + GetProcUUIDPolicyEntrySummary(entry
)
1716 # EndMacro: showprocuuidpolicytable
1718 @lldb_command('showalltaskpolicy')
1719 def ShowAllTaskPolicy(cmd_args
=None):
1721 Routine to print a summary listing of all the tasks
1722 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1723 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1724 io_policy -> RAGE - rapid aging of vnodes requested
1725 NORM - normal I/O explicitly requested (this is the default)
1726 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1727 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1730 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1731 for t
in kern
.tasks
:
1732 pval
= Cast(t
.bsd_info
, 'proc *')
1733 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1734 requested_strings
= [
1735 ["int_darwinbg", "DBG-int"],
1736 ["ext_darwinbg", "DBG-ext"],
1737 ["int_iotier", "iotier-int"],
1738 ["ext_iotier", "iotier-ext"],
1739 ["int_iopassive", "passive-int"],
1740 ["ext_iopassive", "passive-ext"],
1741 ["bg_iotier", "bg-iotier"],
1742 ["terminated", "terminated"],
1743 ["th_pidbind_bg", "bg-pidbind"],
1744 ["t_apptype", "apptype"],
1745 ["t_boosted", "boosted"],
1747 ["t_tal_enabled", "tal-enabled"],
1748 ["t_base_latency_qos", "latency-base"],
1749 ["t_over_latency_qos", "latency-override"],
1750 ["t_base_through_qos", "throughput-base"],
1751 ["t_over_through_qos", "throughput-override"]
1755 for value
in requested_strings
:
1756 if t
.requested_policy
.__getattr
__(value
[0]) :
1757 requested
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1761 suppression_strings
= [
1762 ["t_sup_active", "active"],
1763 ["t_sup_lowpri_cpu", "lowpri-cpu"],
1764 ["t_sup_timer", "timer-throttling"],
1765 ["t_sup_disk", "disk-throttling"],
1766 ["t_sup_cpu_limit", "cpu-limits"],
1767 ["t_sup_suspend", "suspend"],
1768 ["t_sup_bg_sockets", "bg-sockets"]
1772 for value
in suppression_strings
:
1773 if t
.requested_policy
.__getattr
__(value
[0]) :
1774 suppression
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1778 effective_strings
= [
1779 ["darwinbg", "background"],
1780 ["lowpri_cpu", "lowpri-cpu"],
1781 ["io_tier", "iotier"],
1782 ["io_passive", "passive"],
1783 ["all_sockets_bg", "bg-allsockets"],
1784 ["new_sockets_bg", "bg-newsockets"],
1785 ["bg_iotier", "bg-iotier"],
1786 ["terminated", "terminated"],
1787 ["t_gpu_deny", "gpu-deny"],
1788 ["t_tal_engaged", "tal-engaged"],
1789 ["t_suspended", "suspended"],
1790 ["t_watchers_bg", "bg-watchers"],
1791 ["t_latency_qos", "latency-qos"],
1792 ["t_through_qos", "throughput-qos"],
1793 ["t_sup_active", "suppression-active"],
1798 for value
in effective_strings
:
1799 if t
.effective_policy
.__getattr
__(value
[0]) :
1800 effective
+=value
[1] + ": " + str(t
.effective_policy
.__getattr
__(value
[0])) + " "
1804 print "requested: " + requested
1805 print "suppression: " + suppression
1806 print "effective: " + effective
1809 @lldb_type_summary(['wait_queue', 'wait_queue_t'])
1810 @header("{: <20s} {: <20s} {: <15s} {:<5s} {:<5s} {: <20s}".format("waitq", "interlock", "policy", "members", "threads", "eventmask"))
1811 def GetWaitQSummary(waitq
):
1812 """ Summarizes the important fields in task structure.
1813 params: task: value - value object representing a task in kernel
1814 returns: str - summary of the task
1817 format_string
= '{: <#020x} {: <#020x} {: <15s} {: <5d} {: <5d} {: <#020x}'
1821 if (waitq
.wq_fifo
== 1) :
1826 if (waitq
.wq_prepost
== 1) :
1829 if (waitq
.wq_type
== 0x3) :
1831 elif (waitq
.wq_type
== 0x2) :
1836 out_string
+= format_string
.format(waitq
, unsigned(waitq
.wq_interlock
.lock_data
), policy
, 0, 0, unsigned(waitq
.wq_eventmask
))
1838 out_string
+= "\n" + GetThreadSummary
.header
1840 for thread
in IterateQueue(waitq
.wq_queue
, "thread_t", "links"):
1841 out_string
+= "\n" + GetThreadSummary(thread
)
1846 @lldb_command('showallsuspendedtasks', '')
1847 def ShowSuspendedTasks(cmd_args
=[], options
={}):
1848 """ Show a list of suspended tasks with their process name summary.
1850 print GetTaskSummary
.header
+ ' ' + GetProcSummary
.header
1851 for t
in kern
.tasks
:
1852 if t
.suspend_count
> 0:
1853 print GetTaskSummary(t
) + ' ' + GetProcSummary(Cast(t
.bsd_info
, 'proc *'))
1857 @lldb_command('showallpte')
1858 def ShowAllPte(cmd_args
=None):
1859 """ Prints out the physical address of the pte for all tasks
1861 head_taskp
= addressof(kern
.globals.tasks
)
1862 taskp
= Cast(head_taskp
.next
, 'task *')
1863 while taskp
!= head_taskp
:
1864 procp
= Cast(taskp
.bsd_info
, 'proc *')
1865 out_str
= "task = {:#x} pte = {:#x}\t".format(taskp
, taskp
.map.pmap
.ttep
)
1867 out_str
+= "{:s}\n".format(procp
.p_comm
)
1871 taskp
= Cast(taskp
.tasks
.next
, 'struct task *')
1873 # EndMacro: showallpte
1875 # Macro: showallrefcounts
1876 @lldb_command('showallrefcounts')
1877 @header("{0: <20s} {1: ^10s}".format("task", "ref_count"))
1878 def ShowAllRefCounts(cmd_args
=None):
1879 """ Prints the ref_count of all tasks
1882 head_taskp
= addressof(kern
.globals.tasks
)
1883 taskp
= Cast(head_taskp
.next
, 'task *')
1884 print ShowAllRefCounts
.header
1885 while taskp
!= head_taskp
:
1886 out_str
+= "{: <#20x}".format(taskp
)
1887 out_str
+= "{: ^10d}\n".format(taskp
.ref_count
)
1888 taskp
= Cast(taskp
.tasks
.next
, 'task *')
1890 # EndMacro: showallrefcounts
1892 # Macro: showallrunnablethreads
1893 @lldb_command('showallrunnablethreads')
1894 def ShowAllRunnableThreads(cmd_args
=None):
1895 """ Prints the sched usage information for all threads of each task
1898 for taskp
in kern
.tasks
:
1899 for actp
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'):
1900 if int(actp
.state
& 0x4):
1901 ShowActStack([unsigned(actp
)])
1903 # EndMacro: showallrunnablethreads
1905 # Macro: showallschedusage
1906 @lldb_command('showallschedusage')
1907 @header("{0:<20s} {1:^10s} {2:^10s} {3:^15s}".format("Thread", "Priority", "State", "sched_usage"))
1908 def ShowAllSchedUsage(cmd_args
=None):
1909 """ Prints the sched usage information for all threads of each task
1912 for taskp
in kern
.tasks
:
1913 ShowTask([unsigned(taskp
)])
1914 print ShowAllSchedUsage
.header
1915 for actp
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'):
1916 out_str
= "{: <#20x}".format(actp
)
1917 out_str
+= "{: ^10s}".format(str(int(actp
.sched_pri
)))
1918 state
= int(actp
.state
)
1919 thread_state_chars
= {0:'', 1:'W', 2:'S', 4:'R', 8:'U', 16:'H', 32:'A', 64:'P', 128:'I'}
1921 state_str
+= thread_state_chars
[int(state
& 0x1)]
1922 state_str
+= thread_state_chars
[int(state
& 0x2)]
1923 state_str
+= thread_state_chars
[int(state
& 0x4)]
1924 state_str
+= thread_state_chars
[int(state
& 0x8)]
1925 state_str
+= thread_state_chars
[int(state
& 0x10)]
1926 state_str
+= thread_state_chars
[int(state
& 0x20)]
1927 state_str
+= thread_state_chars
[int(state
& 0x40)]
1928 state_str
+= thread_state_chars
[int(state
& 0x80)]
1929 out_str
+= "{: ^10s}".format(state_str
)
1930 out_str
+= "{: >15d}".format(actp
.sched_usage
)
1931 print out_str
+ "\n"
1934 # EndMacro: showallschedusage
1936 #Macro: showprocfilessummary
1937 @lldb_command('showprocfilessummary')
1938 @header("{0: <20s} {1: <20s} {2: >10s}".format("Process", "Name", "Number of Open Files"))
1939 def ShowProcFilesSummary(cmd_args
=None):
1940 """ Display the summary of open file descriptors for all processes in task list
1941 Usage: showprocfilessummary
1943 print ShowProcFilesSummary
.header
1944 for proc
in kern
.procs
:
1945 proc_filedesc
= proc
.p_fd
1946 proc_ofiles
= proc_filedesc
.fd_ofiles
1947 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
1950 if proc_filedesc
.fd_nfiles
!= 0:
1951 while count
<= proc_lastfile
:
1952 if unsigned(proc_ofiles
[count
]) != 0:
1953 proc_file_count
+= 1
1955 print "{0: <#020x} {1: <20s} {2: >10d}".format(proc
, proc
.p_comm
, proc_file_count
)
1957 #EndMacro: showprocfilessummary
1959 @lldb_command('workinguserstacks')
1960 def WorkingUserStacks(cmd_args
=None):
1961 """ Print out the user stack for each thread in a task, followed by the user libraries.
1962 Syntax: (lldb) workinguserstacks <task_t>
1965 print "Insufficient arguments" + ShowTaskUserStacks
.__doc
__
1967 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1968 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1969 pval
= Cast(task
.bsd_info
, 'proc *')
1970 print GetTaskSummary(task
) + " " + GetProcSummary(pval
) + "\n \n"
1971 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1972 print "For thread 0x{0:x}".format(thval
)
1974 ShowThreadUserStack([hex(thval
)])
1975 except Exception as exc_err
:
1976 print "Failed to show user stack for thread 0x{0:x}".format(thval
)
1980 print "Enable debugging ('(lldb) xnudebug debug') to see detailed trace."
1981 WorkingUserLibraries([hex(task
)])
1984 @static_var("exec_load_path", 0)
1985 @lldb_command("workingkuserlibraries")
1986 def WorkingUserLibraries(cmd_args
=None):
1987 """ Show binary images known by dyld in target task
1988 For a given user task, inspect the dyld shared library state and print information about all Mach-O images.
1989 Syntax: (lldb)workinguserlibraries <task_t>
1992 print "Insufficient arguments"
1993 print ShowTaskUserLibraries
.__doc
__
1996 print "{0: <18s} {1: <12s} {2: <36s} {3: <50s}".format('address','type','uuid','path')
1997 out_format
= "0x{0:0>16x} {1: <12s} {2: <36s} {3: <50s}"
1998 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task_t')
1999 is_task_64
= int(task
.t_flags
) & 0x1
2000 dyld_all_image_infos_address
= unsigned(task
.all_image_info_addr
)
2002 if dyld_all_image_infos_address
== 0:
2003 print "No dyld shared library information available for task"
2005 vers_info_data
= GetUserDataAsString(task
, dyld_all_image_infos_address
, 112)
2006 version
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t")
2007 cur_data_offset
+= 4
2009 print "Unknown dyld all_image_infos version number %d" % version
2010 image_info_count
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t")
2011 WorkingUserLibraries
.exec_load_path
= 0
2013 image_info_size
= 24
2014 image_info_array_address
= _ExtractDataFromString(vers_info_data
, 8, "uint64_t")
2015 dyld_load_address
= _ExtractDataFromString(vers_info_data
, 8*4, "uint64_t")
2016 dyld_all_image_infos_address_from_struct
= _ExtractDataFromString(vers_info_data
, 8*13, "uint64_t")
2018 image_info_size
= 12
2019 image_info_array_address
= _ExtractDataFromString(vers_info_data
, 4*2, "uint32_t")
2020 dyld_load_address
= _ExtractDataFromString(vers_info_data
, 4*5, "uint32_t")
2021 dyld_all_image_infos_address_from_struct
= _ExtractDataFromString(vers_info_data
, 4*14, "uint32_t")
2022 # Account for ASLR slide before dyld can fix the structure
2023 dyld_load_address
= dyld_load_address
+ (dyld_all_image_infos_address
- dyld_all_image_infos_address_from_struct
)
2026 while i
< image_info_count
:
2027 image_info_address
= image_info_array_address
+ i
* image_info_size
2028 img_data
= GetUserDataAsString(task
, image_info_address
, image_info_size
)
2030 image_info_addr
= _ExtractDataFromString(img_data
, 0, "uint64_t")
2031 image_info_path
= _ExtractDataFromString(img_data
, 8, "uint64_t")
2033 image_info_addr
= _ExtractDataFromString(img_data
, 0, "uint32_t")
2034 image_info_path
= _ExtractDataFromString(img_data
, 4, "uint32_t")
2035 PrintImageInfo(task
, image_info_addr
, image_info_path
)
2038 # load_path might get set when the main executable is processed.
2039 if WorkingUserLibraries
.exec_load_path
!= 0:
2040 PrintImageInfo(task
, dyld_load_address
, WorkingUserLibraries
.exec_load_path
)
2043 # Macro: showstackaftertask
2044 @lldb_command('showstackaftertask','F:')
2045 def Showstackaftertask(cmd_args
=None,cmd_options
={}):
2046 """ Routine to print the thread stacks for all tasks succeeding a given task
2047 Usage: showstackaftertask <0xaddress of task>
2048 or: showstackaftertask -F <taskname>
2050 if "-F" in cmd_options
:
2051 # Find the task pointer corresponding to its task name
2052 find_task_str
= cmd_options
["-F"]
2053 task_list
= FindTasksByName(find_task_str
)
2055 # Iterate through the list of tasks and print all task stacks thereafter
2056 for tval
in task_list
:
2057 ListTaskStacks(tval
)
2061 raise ArgumentError("Insufficient arguments")
2062 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
2064 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
2066 ListTaskStacks(tval
)
2070 # EndMacro: showstackaftertask
2072 def ListTaskStacks(task
):
2073 """ Search for a given task and print the list of all task stacks thereafter.
2075 # Initialize local variable task_flag to mark when a given task is found.
2078 for t
in kern
.tasks
:
2079 if (task_flag
== 1):
2085 # Macro: showstackafterthread
2086 @lldb_command('showstackafterthread')
2087 def Showstackafterthread(cmd_args
= None):
2088 """ Routine to print the stacks of all threads succeeding a given thread.
2089 Usage: Showstackafterthread <0xaddress of thread>
2091 # local variable thread_flag is used to mark when a given thread is found.
2094 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
2096 raise ArgumentError("No arguments passed")
2097 # Iterate through list of all tasks to look up a given thread
2098 for t
in kern
.tasks
:
2100 pval
= Cast(t
.bsd_info
, 'proc *')
2101 print GetTaskSummary
.header
+ " "+ GetProcSummary
.header
2102 print GetTaskSummary(t
) + " "+ GetProcSummary(pval
)
2104 # Look up for a given thread from the the list of threads of a given task
2105 for thval
in IterateQueue(t
.threads
, 'thread *', 'task_threads'):
2106 if (thread_flag
==1):
2108 print " " + GetThreadSummary
.header
2109 print " " + GetThreadSummary(thval
)
2110 print GetThreadBackTrace(thval
, prefix
="\t")+"\n"
2113 if(thval
==threadval
):
2114 pval
= Cast(t
.bsd_info
, 'proc *')
2115 process_name
= "{:s}".format(pval
.p_comm
)
2117 print " *** Continuing to dump the thread stacks from the process *** :" + " " + process_name
2123 def FindVMEntriesForVnode(task
, vn
):
2124 """ returns an array of vme that have the vnode set to defined vnode
2125 each entry in array is of format (vme, start_addr, end_address, protection)
2130 pager_ops_addr
= unsigned(addressof(kern
.globals.vnode_pager_ops
))
2131 debuglog("pager_ops_addr %s" % hex(pager_ops_addr
))
2133 if unsigned(pmap
) == 0:
2135 vme_list_head
= vmmap
.hdr
.links
2136 vme_ptr_type
= gettype('vm_map_entry *')
2137 for vme
in IterateQueue(vme_list_head
, vme_ptr_type
, 'links'):
2139 if unsigned(vme
.is_sub_map
) == 0 and unsigned(vme
.object.vm_object
) != 0:
2140 obj
= vme
.object.vm_object
2149 vn_pager
= Cast(obj
.pager
, 'vnode_pager *')
2150 if unsigned(vn_pager
.pager_ops
) == pager_ops_addr
and unsigned(vn_pager
.vnode_handle
) == unsigned(vn
):
2151 retval
.append((vme
, unsigned(vme
.links
.start
), unsigned(vme
.links
.end
), unsigned(vme
.protection
)))
2155 @lldb_command('showtaskloadinfo')
2156 def ShowTaskLoadInfo(cmd_args
=None, cmd_options
={}):
2157 """ Print the load address and uuid for the process
2158 Usage: (lldb)showtaskloadinfo <task_t>
2161 raise ArgumentError("Insufficient arguments")
2162 t
= kern
.GetValueFromAddress(cmd_args
[0], 'struct task *')
2163 print_format
= "0x{0:x} - 0x{1:x} {2: <50s} (??? - ???) <{3: <36s}> {4: <50s}"
2164 p
= Cast(t
.bsd_info
, 'struct proc *')
2166 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
)
2167 filepath
= GetVnodePath(p
.p_textvp
)
2168 libname
= filepath
.split('/')[-1]
2169 #print "uuid: %s file: %s" % (uuid_out_string, filepath)
2170 mappings
= FindVMEntriesForVnode(t
, p
.p_textvp
)
2177 #print "Load address: %s" % hex(m[1])
2178 print print_format
.format(load_addr
, end_addr
, libname
, uuid_out_string
, filepath
)