2 """ Please make sure you read the README file COMPLETELY BEFORE reading anything below.
3 It is very critical that you read coding guidelines in Section E in README file.
9 from core
.lazytarget
import *
14 def GetProcNameForTask(task
):
15 """ returns a string name of the process. if proc is not valid "unknown" is returned
17 task: value object represeting a task in the kernel.
19 str : A string name of the process linked to the task
21 if not task
or not unsigned(task
.bsd_info
):
23 p
= Cast(task
.bsd_info
, 'proc *')
26 def GetProcPIDForTask(task
):
27 """ returns a int pid of the process. if the proc is not valid, val[5] from audit_token is returned.
29 task: value object representing a task in the kernel
31 int : pid of the process or -1 if not found
33 if task
and unsigned(task
.bsd_info
):
34 p
= Cast(task
.bsd_info
, 'proc *')
35 return unsigned(p
.p_pid
)
38 return unsigned(task
.audit_token
.val
[5])
42 def GetProcInfo(proc
):
43 """ returns a string name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields.
45 proc : value object representing a proc in the kernel
47 str : A string describing various information for process.
50 out_string
+= ("Process {p: <#020x}\n\tname {p.p_comm: <20s}\n\tpid:{p.p_pid: <6d} " +
51 "task:{p.task: <#020x} p_stat:{p.p_stat: <6d} parent pid: {p.p_ppid: <6d}\n"
56 out_string
+= "Cred: euid {:d} ruid {:d} svuid {:d}\n".format(ucred
.cr_posix
.cr_uid
,
57 ucred
.cr_posix
.cr_ruid
,
58 ucred
.cr_posix
.cr_svuid
)
60 flags
= int(proc
.p_flag
)
61 out_string
+= "Flags: {0: <#020x}\n".format(flags
)
66 out_string
+= "\t" + xnudefines
.proc_flag_explain_strings
[i
] + "\n"
67 elif num
== 0x4: #special case for 32bit flag
68 out_string
+= "\t" + xnudefines
.proc_flag_explain_strings
[0] + "\n"
71 out_string
+= "State: "
72 state_val
= proc
.p_stat
73 if state_val
< 1 or state_val
> len(xnudefines
.proc_state_strings
) :
74 out_string
+= "(Unknown)"
76 out_string
+= xnudefines
.proc_state_strings
[int(state_val
)]
80 def GetProcNameForPid(pid
):
81 """ Finds the name of the process corresponding to a given pid
83 pid : int, pid you want to find the procname for
85 str : Name of the process corresponding to the pid, "Unknown" if not found
88 if int(p
.p_pid
) == int(pid
):
92 def GetProcForPid(search_pid
):
93 """ Finds the value object representing a proc in the kernel based on its pid
95 search_pid : int, pid whose proc structure you want to find
97 value : The value object representing the proc, if a proc corresponding
98 to the given pid is found. Returns None otherwise
101 return kern
.globals.initproc
103 headp
= kern
.globals.allproc
104 for proc
in IterateListEntry(headp
, 'struct proc *', 'p_list'):
105 if proc
.p_pid
== search_pid
:
109 @lldb_command('allproc')
110 def AllProc(cmd_args
=None):
111 """ Walk through the allproc structure and print procinfo for each process structure.
113 cmd_args - [] : array of strings passed from lldb command prompt
115 for proc
in kern
.procs
:
116 print GetProcInfo(proc
)
119 @lldb_command('zombproc')
120 def ZombProc(cmd_args
=None):
121 """ Routine to print out all procs in the zombie list
123 cmd_args - [] : array of strings passed from lldb command prompt
125 if len(kern
.zombprocs
) != 0:
126 print "\nZombie Processes:"
127 for proc
in kern
.zombprocs
:
128 print GetProcInfo(proc
) + "\n\n"
130 @lldb_command('zombtasks')
131 def ZombTasks(cmd_args
=None):
132 """ Routine to print out all tasks in the zombie list
136 if len(kern
.zombprocs
) != 0:
137 header
= "\nZombie Tasks:\n"
138 header
+= GetTaskSummary
.header
+ " " + GetProcSummary
.header
139 for proc
in kern
.zombprocs
:
141 t
= Cast(proc
.task
, 'task *')
142 out_str
+= GetTaskSummary(t
) +" "+ GetProcSummary(proc
) + "\n"
147 @lldb_command('zombstacks')
148 def ZombStacks(cmd_args
=None):
149 """ Routine to print out all stacks of tasks that are exiting
152 for proc
in kern
.zombprocs
:
155 print "\nZombie Stacks:"
157 t
= Cast(proc
.task
, 'task *')
161 def GetASTSummary(ast
):
162 """ Summarizes an AST field
177 T - AST_TELEMETRY_USER
178 T - AST_TELEMETRY_KERNEL
179 T - AST_TELEMETRY_WINDOWED
187 thread_state_chars
= {0x0:'', 0x1:'P', 0x2:'Q', 0x4:'U', 0x8:'H', 0x10:'Y', 0x20:'A',
188 0x40:'L', 0x80:'B', 0x100:'K', 0x200:'M', 0x400:'C', 0x800:'C',
189 0x1000:'G', 0x2000:'T', 0x4000:'T', 0x8000:'T', 0x10000:'S',
190 0x20000: 'D', 0x40000: 'I', 0x80000: 'E'}
193 while mask
<= 0x80000:
194 state_str
+= thread_state_chars
[int(state
& mask
)]
200 @lldb_type_summary(['kcdata_descriptor *', 'kcdata_descriptor_t'])
201 @header("{0: <20s} {1: <20s} {2: <20s} {3: <10s} {4: <5s}".format("kcdata_descriptor", "begin_addr", "cur_pos", "size", "flags"))
202 def GetKCDataSummary(kcdata
):
203 """ Summarizes kcdata_descriptor structure
204 params: kcdata: value - value object representing kcdata_descriptor
205 returns: str - summary of the kcdata object
207 format_string
= "{0: <#020x} {1: <#020x} {2: <#020x} {3: <10d} {4: <#05x}"
208 return format_string
.format(kcdata
, kcdata
.kcd_addr_begin
, kcdata
.kcd_addr_end
, kcdata
.kcd_length
, kcdata
.kcd_flags
)
211 @lldb_type_summary(['task', 'task_t'])
212 @header("{0: <20s} {1: <20s} {2: <20s} {3: >5s} {4: <5s}".format("task","vm_map", "ipc_space", "#acts", "flags"))
213 def GetTaskSummary(task
, showcorpse
=False):
214 """ Summarizes the important fields in task structure.
215 params: task: value - value object representing a task in kernel
216 returns: str - summary of the task
219 format_string
= '{0: <#020x} {1: <#020x} {2: <#020x} {3: >5d} {4: <5s}'
220 thread_count
= int(task
.thread_count
)
222 if hasattr(task
, "suppression_generation") and (int(task
.suppression_generation
) & 0x1) == 0x1:
224 if hasattr(task
, "effective_policy") and int(task
.effective_policy
.tep_sup_active
) == 1:
226 if hasattr(task
, "suspend_count") and int(task
.suspend_count
) > 0:
228 if hasattr(task
, 'task_imp_base') and unsigned(task
.task_imp_base
):
229 tib
= task
.task_imp_base
230 if int(tib
.iit_receiver
) == 1:
232 if int(tib
.iit_donor
) == 1:
234 if int(tib
.iit_assertcnt
) > 0:
237 # check if corpse flag is set
238 if unsigned(task
.t_flags
) & 0x20:
240 if unsigned(task
.t_flags
) & 0x40:
243 out_string
+= format_string
.format(task
, task
.map, task
.itk_space
, thread_count
, task_flags
)
244 if showcorpse
is True and unsigned(task
.corpse_info
) != 0:
245 out_string
+= " " + GetKCDataSummary(task
.corpse_info
)
248 def GetThreadName(thread
):
249 """ Get the name of a thread, if possible. Returns the empty string
252 if int(thread
.uthread
) != 0:
253 uthread
= Cast(thread
.uthread
, 'uthread *')
254 if int(uthread
.pth_name
) != 0 :
255 th_name_strval
= Cast(uthread
.pth_name
, 'char *')
256 if len(str(th_name_strval
)) > 0 :
257 return str(th_name_strval
)
261 @lldb_type_summary(['thread *', 'thread_t'])
262 @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'))
263 def GetThreadSummary(thread
):
264 """ Summarize the thread structure. It decodes the wait state and waitevents from the data in the struct.
265 params: thread: value - value objecte representing a thread in kernel
266 returns: str - summary of a thread
274 A - Terminated and on termination queue
285 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}"
286 thread_ptr_str
= str("{0: <#020x}".format(thread
))
287 if int(thread
.static_param
) :
288 thread_ptr_str
+="[WQ]"
289 thread_id
= hex(thread
.thread_id
)
290 processor
= hex(thread
.last_processor
)
291 base_priority
= str(int(thread
.base_pri
))
292 sched_priority
= str(int(thread
.sched_pri
))
294 mode
= str(thread
.sched_mode
)
295 if "TIMESHARE" in mode
:
296 sched_mode
+="timeshare"
297 elif "FIXED" in mode
:
299 elif "REALTIME" in mode
:
300 sched_mode
+="realtime"
302 if (unsigned(thread
.bound_processor
) != 0):
306 if (unsigned(thread
.sched_flags
) & 0x0004):
310 thread_name
= GetThreadName(thread
)
311 if int(thread
.uthread
) != 0:
312 uthread
= Cast(thread
.uthread
, 'uthread *')
314 #check for io_policy flags
315 if int(uthread
.uu_flag
) & 0x400:
316 io_policy_str
+='RAGE '
318 #now flags for task_policy
322 if int(thread
.effective_policy
.thep_darwinbg
) != 0:
324 if int(thread
.effective_policy
.thep_io_tier
) != 0:
326 if int(thread
.effective_policy
.thep_io_passive
) != 0:
328 if int(thread
.effective_policy
.thep_terminated
) != 0:
331 state
= int(thread
.state
)
332 thread_state_chars
= {0x0:'', 0x1:'W', 0x2:'S', 0x4:'R', 0x8:'U', 0x10:'H', 0x20:'A', 0x40:'P', 0x80:'I'}
336 state_str
+= thread_state_chars
[int(state
& mask
)]
339 if int(thread
.inspection
):
342 ast
= int(thread
.ast
) |
int(thread
.reason
)
343 ast_str
= GetASTSummary(ast
)
345 #wait queue information
349 if ( state
& 0x1 ) != 0:
350 #we need to look at the waitqueue as well
351 wait_queue_str
= str("{0: <#020x}".format(int(hex(thread
.waitq
), 16)))
352 wait_event_str
= str("{0: <#020x}".format(int(hex(thread
.wait_event
), 16)))
353 wait_event_str_sym
= kern
.Symbolicate(int(hex(thread
.wait_event
), 16))
354 if len(wait_event_str_sym
) > 0:
355 wait_event_str
= wait_event_str
.strip() + " <" + wait_event_str_sym
+ ">"
356 if int(thread
.uthread
) != 0 :
357 uthread
= Cast(thread
.uthread
, 'uthread *')
358 if int(uthread
.uu_wmesg
) != 0:
359 wait_message
= str(Cast(uthread
.uu_wmesg
, 'char *'))
361 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
)
365 def GetTaskRoleString(role
):
367 0 : "TASK_UNSPECIFIED",
368 1 : "TASK_FOREGROUND_APPLICATION",
369 2 : "TASK_BACKGROUND_APPLICATION",
370 3 : "TASK_CONTROL_APPLICATION",
371 4 : "TASK_GRAPHICS_SERVER",
372 5 : "TASK_THROTTLE_APPLICATION",
373 6 : "TASK_NONUI_APPLICATION",
374 7 : "TASK_DEFAULT_APPLICATION",
376 return role_strs
[int(role
)]
378 def GetCoalitionFlagString(coal
):
380 if (coal
.privileged
):
381 flags
.append('privileged')
382 if (coal
.termrequested
):
383 flags
.append('termrequested')
384 if (coal
.terminated
):
385 flags
.append('terminated')
387 flags
.append('reaped')
389 flags
.append('notified')
391 flags
.append('efficient')
392 return "|".join(flags
)
394 def GetCoalitionTasks(queue
, coal_type
, thread_details
=False):
396 0x0 : "SFI_CLASS_UNSPECIFIED",
397 0x1 : "SFI_CLASS_DARWIN_BG",
398 0x2 : "SFI_CLASS_APP_NAP",
399 0x3 : "SFI_CLASS_MANAGED_FOCAL",
400 0x4 : "SFI_CLASS_MANAGED_NONFOCAL",
401 0x5 : "SFI_CLASS_DEFAULT_FOCAL",
402 0x6 : "SFI_CLASS_DEFAULT_NONFOCAL",
403 0x7 : "SFI_CLASS_KERNEL",
404 0x8 : "SFI_CLASS_OPTED_OUT",
405 0x9 : "SFI_CLASS_UTILITY",
406 0xA : "SFI_CLASS_LEGACY_FOCAL",
407 0xB : "SFI_CLASS_LEGACY_NONFOCAL",
408 0xC : "SFI_CLASS_USER_INITIATED_FOCAL",
409 0xD : "SFI_CLASS_USER_INITIATED_NONFOCAL",
410 0xE : "SFI_CLASS_USER_INTERACTIVE_FOCAL",
411 0xF : "SFI_CLASS_USER_INTERACTIVE_NONFOCAL",
412 0x10 : "SFI_CLASS_MAINTENANCE",
415 field_name
= 'task_coalition'
416 for task
in IterateLinkageChain(queue
, 'task *', field_name
, coal_type
* sizeof('queue_chain_t')):
417 task_str
= "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(task
),task
,GetProcNameForTask(task
),GetTaskRoleString(task
.effective_policy
.tep_role
))
419 for thread
in IterateQueue(task
.threads
, "thread_t", "task_threads"):
420 task_str
+= "\n\t\t\t|-> thread:" + hex(thread
) + ", " + sfi_strs
[int(thread
.sfi_class
)]
421 tasks
.append(task_str
)
424 def GetCoalitionTypeString(type):
425 """ Convert a coalition type field into a string
426 Currently supported types (from <mach/coalition.h>):
427 COALITION_TYPE_RESOURCE
428 COALITION_TYPE_JETSAM
430 if type == 0: # COALITION_TYPE_RESOURCE
436 def GetResourceCoalitionSummary(coal
, verbose
=False):
437 """ Summarize a resource coalition
439 out_string
= "Resource Coalition:\n\t Ledger:\n"
440 thread_details
= False
441 if config
['verbosity'] > vSCRIPT
:
442 thread_details
= True
443 ledgerp
= coal
.r
.ledger
444 if verbose
and unsigned(ledgerp
) != 0:
446 while i
!= ledgerp
.l_template
.lt_cnt
:
448 out_string
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, ledgerp
.l_entries
[i
], i
)
450 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
)
451 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
)
452 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
)
453 out_string
+= "\n\t cpu_ptime {0: <d}".format(coal
.r
.cpu_ptime
)
454 out_string
+= "\n\t Tasks:\n\t\t"
455 tasks
= GetCoalitionTasks(addressof(coal
.r
.tasks
), 0, thread_details
)
456 out_string
+= "\n\t\t".join(tasks
)
459 def GetJetsamCoalitionSummary(coal
, verbose
=False):
460 out_string
= "Jetsam Coalition:"
461 thread_details
= False
462 if config
['verbosity'] > vSCRIPT
:
463 thread_details
= True
464 if unsigned(coal
.j
.leader
) == 0:
465 out_string
+= "\n\t NO Leader!"
467 out_string
+= "\n\t Leader:\n\t\t"
468 out_string
+= "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(coal
.j
.leader
),coal
.j
.leader
,GetProcNameForTask(coal
.j
.leader
),GetTaskRoleString(coal
.j
.leader
.effective_policy
.tep_role
))
469 out_string
+= "\n\t Extensions:\n\t\t"
470 tasks
= GetCoalitionTasks(addressof(coal
.j
.extensions
), 1, thread_details
)
471 out_string
+= "\n\t\t".join(tasks
)
472 out_string
+= "\n\t XPC Services:\n\t\t"
473 tasks
= GetCoalitionTasks(addressof(coal
.j
.services
), 1, thread_details
)
474 out_string
+= "\n\t\t".join(tasks
)
475 out_string
+= "\n\t Other Tasks:\n\t\t"
476 tasks
= GetCoalitionTasks(addressof(coal
.j
.other
), 1, thread_details
)
477 out_string
+= "\n\t\t".join(tasks
)
478 out_string
+= "\n\t Thread Group: {0: <#020x}\n".format(coal
.j
.thread_group
)
481 @lldb_type_summary(['coalition_t', 'coalition *'])
482 @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"))
483 def GetCoalitionSummary(coal
):
484 if unsigned(coal
) == 0:
485 return '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'.format(0, "", -1, -1, -1, -1, -1, "")
487 format_string
= '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'
488 type_string
= GetCoalitionTypeString(coal
.type)
489 flag_string
= GetCoalitionFlagString(coal
)
490 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
)
493 def GetCoalitionInfo(coal
, verbose
=False):
494 """ returns a string describing a coalition, including details about the particular coalition type.
496 coal : value object representing a coalition in the kernel
498 str : A string describing the coalition.
500 if unsigned(coal
) == 0:
501 return "<null coalition>"
502 typestr
= GetCoalitionTypeString(coal
.type)
503 flagstr
= GetCoalitionFlagString(coal
)
505 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
)
506 if coal
.type == 0: # COALITION_TYPE_RESOURCE
507 out_string
+= GetResourceCoalitionSummary(coal
, verbose
)
508 elif coal
.type == 1: # COALITION_TYPE_JETSAM
509 out_string
+= GetJetsamCoalitionSummary(coal
, verbose
)
511 out_string
+= "Unknown Type"
515 # Macro: showcoalitioninfo
517 @lldb_command('showcoalitioninfo')
518 def ShowCoalitionInfo(cmd_args
=None, cmd_options
={}):
519 """ Display more detailed information about a coalition
520 Usage: showcoalitioninfo <address of coalition>
523 if config
['verbosity'] > vHUMAN
:
526 raise ArgumentError("No arguments passed")
527 coal
= kern
.GetValueFromAddress(cmd_args
[0], 'coalition *')
529 print "unknown arguments:", str(cmd_args
)
531 print GetCoalitionInfo(coal
, verbose
)
533 # EndMacro: showcoalitioninfo
535 # Macro: showallcoalitions
537 @lldb_command('showallcoalitions')
538 def ShowAllCoalitions(cmd_args
=None):
539 """ Print a summary listing of all the coalitions
542 print GetCoalitionSummary
.header
543 for c
in kern
.coalitions
:
544 print GetCoalitionSummary(c
)
546 # EndMacro: showallcoalitions
548 # Macro: showallthreadgroups
550 @lldb_type_summary(['thread_group_t', 'thread_group *'])
551 @header("{0: <20s} {1: <5s} {2: <16s} {3: <5s} {4: <8s} {5: <20s}".format("thread_group", "id", "name", "refc", "flags", "recommendation"))
552 def GetThreadGroupSummary(tg
):
553 if unsigned(tg
) == 0:
554 return '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}'.format(0, -1, "", -1, "", -1)
556 format_string
= '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}'
558 if (tg
.tg_flags
& 0x1):
560 if (tg
.tg_flags
& 0x2):
562 out_string
+= format_string
.format(tg
, tg
.tg_id
, tg
.tg_name
, tg
.tg_refcount
, tg_flags
, tg
.tg_recommendation
)
565 @lldb_command('showallthreadgroups')
566 def ShowAllThreadGroups(cmd_args
=None):
567 """ Print a summary listing of all thread groups
570 print GetThreadGroupSummary
.header
571 for tg
in kern
.thread_groups
:
572 print GetThreadGroupSummary(tg
)
574 # EndMacro: showallthreadgroups
576 # Macro: showtaskcoalitions
578 @lldb_command('showtaskcoalitions', 'F:')
579 def ShowTaskCoalitions(cmd_args
=None, cmd_options
={}):
583 if "-F" in cmd_options
:
584 task_list
= FindTasksByName(cmd_options
["-F"])
586 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
589 raise ArgumentError("No arguments passed")
591 if len(task_list
) > 0:
592 print GetCoalitionSummary
.header
593 for task
in task_list
:
594 print GetCoalitionSummary(task
.coalition
[0])
595 print GetCoalitionSummary(task
.coalition
[1])
597 # EndMacro: showtaskcoalitions
599 @lldb_type_summary(['proc', 'proc *'])
600 @header("{0: >6s} {1: ^20s} {2: >14s} {3: ^10s} {4: <20s}".format("pid", "process", "io_policy", "wq_state", "command"))
601 def GetProcSummary(proc
):
602 """ Summarize the process data.
604 proc : value - value representaitng a proc * in kernel
606 str - string summary of the process.
609 format_string
= "{0: >6d} {1: >#020x} {2: >14s} {3: >2d} {4: >2d} {5: >2d} {6: <20s}"
610 pval
= proc
.GetSBValue()
611 #code.interact(local=locals())
612 if str(pval
.GetType()) != str(gettype('proc *')) :
613 return "Unknown type " + str(pval
.GetType()) + " " + str(hex(proc
))
615 out_string
+= "Process " + hex(proc
) + " is not valid."
617 pid
= int(proc
.p_pid
)
618 proc_addr
= int(hex(proc
), 16)
620 if int(proc
.p_lflag
) & 0x400000 :
621 proc_rage_str
= "RAGE"
623 task
= Cast(proc
.task
, 'task *')
627 if int(task
.effective_policy
.tep_darwinbg
) != 0:
629 if int(task
.effective_policy
.tep_lowpri_cpu
) != 0:
632 if int(task
.effective_policy
.tep_io_tier
) != 0:
634 if int(task
.effective_policy
.tep_io_passive
) != 0:
636 if int(task
.effective_policy
.tep_terminated
) != 0:
639 if int(task
.effective_policy
.tep_latency_qos
) != 0:
641 if int(task
.effective_policy
.tep_sup_active
) != 0:
646 work_queue
= Cast(proc
.p_wqptr
, 'workqueue *')
647 if proc
.p_wqptr
!= 0 :
648 wq_num_threads
= int(work_queue
.wq_nthreads
)
649 wq_idle_threads
= int(work_queue
.wq_thidlecount
)
650 wq_req_threads
= int(work_queue
.wq_reqcount
)
659 process_name
= str(proc
.p_comm
)
660 if process_name
== 'xpcproxy':
661 for thread
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
662 thread_name
= GetThreadName(thread
)
664 process_name
+= ' (' + thread_name
+ ')'
666 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
)
669 @lldb_type_summary(['tty_dev_t', 'tty_dev_t *'])
670 @header("{0: <20s} {1: <10s} {2: <10s} {3: <15s} {4: <15s} {5: <15s} {6: <15s}".format("tty_dev","master", "slave", "open", "free", "name", "revoke"))
671 def GetTTYDevSummary(tty_dev
):
672 """ Summarizes the important fields in tty_dev_t structure.
673 params: tty_dev: value - value object representing a tty_dev_t in kernel
674 returns: str - summary of the tty_dev
677 format_string
= "{0: <#020x} {1: <#010x} {2: <#010x} {3: <15s} {4: <15s} {5: <15s} {6: <15s}"
678 open_fn
= kern
.Symbolicate(int(hex(tty_dev
.open), 16))
679 free_fn
= kern
.Symbolicate(int(hex(tty_dev
.free
), 16))
680 name_fn
= kern
.Symbolicate(int(hex(tty_dev
.name
), 16))
681 revoke_fn
= kern
.Symbolicate(int(hex(tty_dev
.revoke
), 16))
682 out_string
+= format_string
.format(tty_dev
, tty_dev
.master
, tty_dev
.slave
, open_fn
, free_fn
, name_fn
, revoke_fn
)
687 @lldb_command('showtask', 'F:')
688 def ShowTask(cmd_args
=None, cmd_options
={}):
689 """ Routine to print a summary listing of given task
690 Usage: showtask <address of task>
691 or : showtask -F <name of task>
694 if "-F" in cmd_options
:
695 task_list
= FindTasksByName(cmd_options
['-F'])
698 raise ArgumentError("Invalid arguments passed.")
700 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
702 raise ("Unknown arguments: %r" % cmd_args
)
703 task_list
.append(tval
)
705 for tval
in task_list
:
706 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
707 pval
= Cast(tval
.bsd_info
, 'proc *')
708 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
714 @lldb_command('showpid')
715 def ShowPid(cmd_args
=None):
716 """ Routine to print a summary listing of task corresponding to given pid
717 Usage: showpid <pid value>
720 raise ArgumentError("No arguments passed")
721 pidval
= ArgumentStringToInt(cmd_args
[0])
723 pval
= Cast(t
.bsd_info
, 'proc *')
724 if pval
and pval
.p_pid
== pidval
:
725 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
726 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
733 @lldb_command('showproc')
734 def ShowProc(cmd_args
=None):
735 """ Routine to print a summary listing of task corresponding to given proc
736 Usage: showproc <address of proc>
739 raise ArgumentError("No arguments passed")
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 raise ArgumentError("No arguments passed")
760 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
762 print "unknown arguments:", str(cmd_args
)
764 print GetProcInfo(pval
)
766 # EndMacro: showprocinfo
768 #Macro: showprocfiles
770 @lldb_command('showprocfiles')
771 def ShowProcFiles(cmd_args
=None):
772 """ Given a proc_t pointer, display the list of open file descriptors for the referenced process.
773 Usage: showprocfiles <proc_t>
776 print ShowProcFiles
.__doc
__
778 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc_t')
779 proc_filedesc
= proc
.p_fd
780 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
781 proc_ofiles
= proc_filedesc
.fd_ofiles
782 if unsigned(proc_ofiles
) == 0:
783 print 'No open files for proc {0: <s}'.format(cmd_args
[0])
785 print "{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO')
786 print "{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("")
789 while count
<= proc_lastfile
:
790 if unsigned(proc_ofiles
[count
]) != 0:
792 proc_fd_flags
= proc_ofiles
[count
].f_flags
793 proc_fd_fglob
= proc_ofiles
[count
].f_fglob
794 out_str
+= "{0: <5d} ".format(count
)
795 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
))
796 out_str
+= "0x{0:0>8x} ".format(unsigned(proc_fd_flags
))
797 proc_fd_ftype
= unsigned(proc_fd_fglob
.fg_ops
.fo_type
)
798 if proc_fd_ftype
in xnudefines
.filetype_strings
:
799 out_str
+= "{0: <8s} ".format(xnudefines
.filetype_strings
[proc_fd_ftype
])
801 out_str
+= "?: {0: <5d} ".format(proc_fd_ftype
)
802 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
.fg_data
))
803 if proc_fd_ftype
== 1:
804 fd_name
= Cast(proc_fd_fglob
.fg_data
, 'struct vnode *').v_name
805 out_str
+= "{0: <64s}".format(fd_name
)
810 #EndMacro: showprocfiles
814 @lldb_command('showtty')
815 def ShowTTY(cmd_args
=None):
816 """ Display information about a struct tty
817 Usage: showtty <tty struct>
820 print ShowTTY
.__doc
__
823 tty
= kern
.GetValueFromAddress(cmd_args
[0], 'struct tty *')
824 print "TTY structure at: {0: <s}".format(cmd_args
[0])
825 print "Last input to raw queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_rawq
.c_cs
), tty
.t_rawq
.c_cs
)
826 print "Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_canq
.c_cs
), tty
.t_canq
.c_cs
)
827 print "Last output data: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_outq
.c_cs
), tty
.t_outq
.c_cs
)
829 ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'],
830 ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'],
831 ['', 'TS_BUSY (Draining output)'],
832 ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'],
833 ['', 'TS_FLUSH (Outq has been flushed during DMA)'],
834 ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'],
835 ['', 'TS_TBLOCK (Further input blocked)'],
836 ['', 'TS_TIMEOUT (Wait for output char processing)'],
837 ['', 'TS_TTSTOP (Output paused)'],
838 ['', 'TS_WOPEN (Open in progress)'],
839 ['', 'TS_XCLUDE (Tty requires exclusivity)'],
840 ['', 'TS_BKSL (State for lowercase \\ work)'],
841 ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'],
842 ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'],
843 ['', 'TS_LNCH (Next character is literal)'],
844 ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'],
845 ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'],
846 ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'],
847 ['', 'TS_SNOOP (Device is being snooped on)'],
848 ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'],
849 ['', 'TS_ZOMBIE (Connection lost)'],
850 ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'],
851 ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'],
852 ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)']
856 tty_state
= unsigned(tty
.t_state
)
859 if tty_state
& mask
!= 0:
860 if len(tty_state_info
[index
][1]) > 0:
861 print '\t' + tty_state_info
[index
][1]
863 if len(tty_state_info
[index
][0]) > 0:
864 print '\t' + tty_state_info
[index
][0]
867 print "Flags: 0x{0:0>8x}".format(unsigned(tty
.t_flags
))
868 print "Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty
.t_pgrp
))
869 print "Enclosing session: 0x{0:0>16x}".format(unsigned(tty
.t_session
))
871 print "\tInput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_iflag
))
872 print "\tOutput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_oflag
))
873 print "\tControl Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_cflag
))
874 print "\tLocal Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_lflag
))
875 print "\tInput Speed: {0: <8d}".format(tty
.t_termios
.c_ispeed
)
876 print "\tOutput Speed: {0: <8d}".format(tty
.t_termios
.c_ospeed
)
877 print "High Watermark: {0: <d} bytes".format(tty
.t_hiwat
)
878 print "Low Watermark : {0: <d} bytes".format(tty
.t_lowat
)
882 #Macro showallttydevs
884 @lldb_command('showallttydevs')
885 def ShowAllTTYDevs(cmd_args
=[], cmd_options
={}):
886 """ Show a list of ttydevs registered in the system.
890 tty_dev_head
= kern
.globals.tty_dev_head
891 tty_dev
= tty_dev_head
892 print GetTTYDevSummary
.header
893 while unsigned(tty_dev
) != 0:
894 print GetTTYDevSummary(tty_dev
)
895 tty_dev
= tty_dev
.next
898 #EndMacro: showallttydevs
900 #Macro: dumpthread_terminate_queue
902 @lldb_command('dumpthread_terminate_queue')
903 def DumpThreadTerminateQueue(cmd_args
=None):
904 """ Displays the contents of the specified call_entry queue.
905 Usage: dumpthread_terminate_queue
909 print GetThreadSummary
.header
910 for th
in IterateQueue(addressof(kern
.globals.thread_terminate_queue
), 'struct thread *', 'q_link'):
911 print GetThreadSummary(th
)
913 print "{0: <d} entries!".format(count
)
915 #EndMacro: dumpthread_terminate_queue
917 #Macro: dumpcrashed_thread_queue
919 @lldb_command('dumpcrashed_thread_queue')
920 def DumpCrashedThreadsQueue(cmd_args
=None):
921 """ Displays the contents of the specified call_entry queue.
922 Usage: dumpcrashed_thread_queue
926 print GetThreadSummary
.header
927 for th
in IterateQueue(addressof(kern
.globals.crashed_threads_queue
), 'struct thread *', 'q_link'):
928 print GetThreadSummary(th
)
930 print "{0: <d} entries!".format(count
)
932 #EndMacro: dumpcrashed_thread_queue
934 #Macro: dumpcallqueue
936 @lldb_command('dumpcallqueue')
937 def DumpCallQueue(cmd_args
=None):
938 """ Displays the contents of the specified call_entry queue.
939 Usage: dumpcallqueue <queue_head_t *>
942 raise ArgumentError("Invalid arguments")
944 print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC')
945 callhead
= kern
.GetValueFromAddress(cmd_args
[0], 'queue_head_t *')
947 for callentry
in IterateQueue(callhead
, 'struct call_entry *', 'q_link'):
948 print "{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format(
949 unsigned(callentry
), unsigned(callentry
.param0
), unsigned(callentry
.param1
),
950 unsigned(callentry
.deadline
), unsigned(callentry
.func
))
952 print "{0: <d} entries!".format(count
)
954 #EndMacro: dumpcallqueue
956 @lldb_command('showalltasklogicalwrites')
957 def ShowAllTaskIOStats(cmd_args
=None):
958 """ Commad to print I/O stats for all tasks
960 print "{0: <20s} {1: <20s} {2: <20s} {3: <20s} {4: <20s} {5: <20s}".format("task", "Immediate Writes", "Deferred Writes", "Invalidated Writes", "Metadata Writes", "name")
962 pval
= Cast(t
.bsd_info
, 'proc *')
963 print "{0: <#18x} {1: >20d} {2: >20d} {3: >20d} {4: >20d} {5: <20s}".format(t
,
964 t
.task_immediate_writes
,
965 t
.task_deferred_writes
,
966 t
.task_invalidated_writes
,
967 t
.task_metadata_writes
,
971 @lldb_command('showalltasks','C')
972 def ShowAllTasks(cmd_args
=None, cmd_options
={}):
973 """ Routine to print a summary listing of all the tasks
974 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
975 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
976 io_policy -> RAGE - rapid aging of vnodes requested
977 NORM - normal I/O explicitly requested (this is the default)
978 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
979 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
980 Usage: (lldb) showalltasks -C : describe the corpse structure
985 if '-C' in cmd_options
:
987 extra_hdr
+= " " + GetKCDataSummary
.header
989 print GetTaskSummary
.header
+ extra_hdr
+ " " + GetProcSummary
.header
991 pval
= Cast(t
.bsd_info
, 'proc *')
992 out_str
= GetTaskSummary(t
, showcorpse
) + " " + GetProcSummary(pval
)
996 @lldb_command('taskforpmap')
997 def TaskForPmap(cmd_args
=None):
998 """ Find the task whose pmap corresponds to <pmap>.
999 Syntax: (lldb) taskforpmap <pmap>
1000 Multiple -v's can be specified for increased verbosity
1002 if cmd_args
== None or len(cmd_args
) < 1:
1003 raise ArgumentError("Too few arguments to taskforpmap.")
1004 pmap
= kern
.GetValueFromAddress(cmd_args
[0], 'pmap_t')
1005 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1006 for tasklist
in [kern
.tasks
, kern
.terminated_tasks
]:
1008 if t
.map.pmap
== pmap
:
1009 pval
= Cast(t
.bsd_info
, 'proc *')
1010 out_str
= GetTaskSummary(t
) + " " + GetProcSummary(pval
)
1013 @lldb_command('showterminatedtasks')
1014 def ShowTerminatedTasks(cmd_args
=None):
1015 """ Routine to print a summary listing of all the terminated tasks
1016 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1017 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1018 io_policy -> RAGE - rapid aging of vnodes requested
1019 NORM - normal I/O explicitly requested (this is the default)
1020 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1021 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1022 syntax: (lldb)showallterminatedtasks
1025 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1026 for t
in kern
.terminated_tasks
:
1027 pval
= Cast(t
.bsd_info
, 'proc *')
1028 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1031 # Macro: showtaskstacks
1033 def ShowTaskStacks(task
):
1034 """ Print a task with summary and stack information for each of its threads
1037 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1038 pval
= Cast(task
.bsd_info
, 'proc *')
1039 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1040 for th
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1041 print " " + GetThreadSummary
.header
1042 print " " + GetThreadSummary(th
)
1043 print GetThreadBackTrace(th
, prefix
=" ") + "\n"
1045 def FindTasksByName(searchstr
, ignore_case
=True):
1046 """ Search the list of tasks by name.
1048 searchstr: str - a regex like string to search for task
1049 ignore_case: bool - If False then exact matching will be enforced
1051 [] - array of task object. Empty if not found any
1055 re_options
= re
.IGNORECASE
1056 search_regex
= re
.compile(searchstr
, re_options
)
1058 for t
in kern
.tasks
:
1059 pval
= Cast(t
.bsd_info
, "proc *")
1060 process_name
= "{:s}".format(pval
.p_comm
)
1061 if search_regex
.search(process_name
):
1065 @lldb_command('showtaskstacks', 'F:')
1066 def ShowTaskStacksCmdHelper(cmd_args
=None, cmd_options
={}):
1067 """ Routine to print out the stack for each thread in a task
1068 Usage: showtaskstacks <0xaddress of task>
1069 or: showtaskstacks -F launchd
1072 if "-F" in cmd_options
:
1073 find_task_str
= cmd_options
["-F"]
1074 task_list
= FindTasksByName(find_task_str
)
1075 for tval
in task_list
:
1076 ShowTaskStacks(tval
)
1080 raise ArgumentError("No arguments passed")
1082 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1084 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
1086 ShowTaskStacks(tval
)
1089 # EndMacro: showtaskstacks
1091 def CheckTaskProcRefs(task
, proc
):
1092 for thread
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1093 if int(thread
.uthread
) == 0:
1095 uthread
= Cast(thread
.uthread
, 'uthread *')
1096 refcount
= int(uthread
.uu_proc_refcount
)
1097 uu_ref_index
= int(uthread
.uu_pindex
)
1100 for ref
in range(0, uu_ref_index
):
1101 if unsigned(uthread
.uu_proc_ps
[ref
]) == unsigned(proc
):
1102 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1103 pval
= Cast(task
.bsd_info
, 'proc *')
1104 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1105 print "\t" + GetThreadSummary
.header
1106 print "\t" + GetThreadSummary(thread
) + "\n"
1108 for frame
in range (0, 10):
1109 trace_addr
= unsigned(uthread
.uu_proc_pcs
[ref
][frame
])
1110 symbol_arr
= kern
.SymbolicateFromAddress(unsigned(trace_addr
))
1112 symbol_str
= str(symbol_arr
[0].addr
)
1115 print '{0: <#x} {1: <s}'.format(trace_addr
, symbol_str
)
1118 @lldb_command('showprocrefs')
1119 def ShowProcRefs(cmd_args
= None):
1120 """ Display information on threads/BTs that could be holding a reference on the specified proc
1121 NOTE: We can't say affirmatively if any of these references are still held since
1122 there's no way to pair references with drop-refs in the current infrastructure.
1123 Usage: showprocrefs <proc>
1125 if cmd_args
== None or len(cmd_args
) < 1:
1126 raise ArgumentError("No arguments passed")
1128 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
1130 for t
in kern
.tasks
:
1131 CheckTaskProcRefs(t
, proc
)
1132 for t
in kern
.terminated_tasks
:
1133 CheckTaskProcRefs(t
, proc
)
1137 @lldb_command('showallthreads')
1138 def ShowAllThreads(cmd_args
= None):
1139 """ Display info about all threads in the system
1141 for t
in kern
.tasks
:
1142 ShowTaskThreads([str(int(t
))])
1145 for t
in kern
.terminated_tasks
:
1146 print "Terminated: \n"
1147 ShowTaskThreads([str(int(t
))])
1152 @lldb_command('showtaskthreads', "F:")
1153 def ShowTaskThreads(cmd_args
= None, cmd_options
={}):
1154 """ Display thread information for a given task
1155 Usage: showtaskthreads <0xaddress of task>
1156 or: showtaskthreads -F <name>
1159 if "-F" in cmd_options
:
1160 task_list
= FindTasksByName(cmd_options
["-F"])
1162 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1165 raise ArgumentError("No arguments passed")
1167 for task
in task_list
:
1168 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1169 pval
= Cast(task
.bsd_info
, 'proc *')
1170 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1171 print "\t" + GetThreadSummary
.header
1172 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1173 print "\t" + GetThreadSummary(thval
)
1176 @lldb_command('showact')
1177 def ShowAct(cmd_args
=None):
1178 """ Routine to print out the state of a specific thread.
1179 usage: showact <activation>
1182 raise ArgumentError("No arguments passed")
1183 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1184 print GetThreadSummary
.header
1185 print GetThreadSummary(threadval
)
1187 @lldb_command('showactstack')
1188 def ShowActStack(cmd_args
=None):
1189 """ Routine to print out the stack of a specific thread.
1190 usage: showactstack <activation>
1193 raise ArgumentError("No arguments passed")
1194 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1195 print GetThreadSummary
.header
1196 print GetThreadSummary(threadval
)
1197 print GetThreadBackTrace(threadval
, prefix
="\t")
1200 @lldb_command('switchtoact')
1201 def SwitchToAct(cmd_args
=None):
1202 """ Switch to different context specified by activation
1203 This command allows gdb to examine the execution context and call
1204 stack for the specified activation. For example, to view the backtrace
1205 for an activation issue "switchtoact <address>", followed by "bt".
1206 Before resuming execution, issue a "resetctx" command, to
1207 return to the original execution context.
1209 if cmd_args
is None or len(cmd_args
) < 1:
1210 raise ArgumentError("No arguments passed")
1211 thval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1212 lldbthread
= GetLLDBThreadForKernelThread(thval
)
1213 print GetThreadSummary
.header
1214 print GetThreadSummary(thval
)
1215 LazyTarget
.GetProcess().selected_thread
= lldbthread
1216 if not LazyTarget
.GetProcess().SetSelectedThread(lldbthread
):
1217 print "Failed to switch thread."
1220 @lldb_command('switchtoregs')
1221 def SwitchToRegs(cmd_args
=None):
1222 """ Routine to switch to a register state.
1223 Usage: (lldb) switchtoregs <struct arm_saved_state[64] *>
1224 This command creates a fake thread in lldb with the saved register state.
1225 Note: This command ONLY works for ARM based kernel setup.
1228 if cmd_args
== None or len(cmd_args
) < 1:
1229 raise ArgumentError("No arguments passed")
1231 lldb_process
= LazyTarget
.GetProcess()
1233 saved_state
= ArgumentStringToInt(cmd_args
[0])
1234 # any change to this logic requires change in operating_system.py as well
1235 fake_thread_id
= 0xdead0000 |
(saved_state
& ~
0xffff0000)
1236 fake_thread_id
= fake_thread_id
& 0xdeadffff
1237 lldb_process
.CreateOSPluginThread(0xdeadbeef, saved_state
)
1238 lldbthread
= lldb_process
.GetThreadByID(int(fake_thread_id
))
1240 if not lldbthread
.IsValid():
1241 print "Failed to create thread"
1244 lldb_process
.selected_thread
= lldbthread
1245 if not lldb_process
.SetSelectedThread(lldbthread
):
1246 print "Failed to switch thread"
1247 print "Switched to Fake thread created from register state at 0x%x" % saved_state
1251 # Macro: showallstacks
1252 @lldb_command('showallstacks')
1253 def ShowAllStacks(cmd_args
=None):
1254 """Routine to print out the stack for each thread in the system.
1256 for t
in kern
.tasks
:
1262 # EndMacro: showallstacks
1264 # Macro: showcurrentstacks
1265 @lldb_command('showcurrentstacks')
1266 def ShowCurrentStacks(cmd_args
=None):
1267 """ Routine to print out the thread running on each cpu (incl. its stack)
1269 processor_list
= kern
.GetGlobalVariable('processor_list')
1270 current_processor
= processor_list
1271 while unsigned(current_processor
) > 0:
1272 print "\n" + GetProcessorSummary(current_processor
)
1273 active_thread
= current_processor
.active_thread
1274 if unsigned(active_thread
) != 0 :
1275 task_val
= active_thread
.task
1276 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1277 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1278 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1279 print "\t" + GetThreadSummary
.header
1280 print "\t" + GetThreadSummary(active_thread
)
1281 print "\tBacktrace:"
1282 print GetThreadBackTrace(active_thread
, prefix
="\t")
1283 current_processor
= current_processor
.processor_list
1285 # EndMacro: showcurrentstacks
1287 @lldb_command('showcurrentthreads')
1288 def ShowCurrentThreads(cmd_args
=None):
1289 """ Display info about threads running on each cpu """
1290 processor_list
= kern
.GetGlobalVariable('processor_list')
1291 current_processor
= processor_list
1292 while unsigned(current_processor
) > 0:
1293 print GetProcessorSummary(current_processor
)
1294 active_thread
= current_processor
.active_thread
1295 if unsigned(active_thread
) != 0 :
1296 task_val
= active_thread
.task
1297 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1298 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1299 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1300 print "\t" + GetThreadSummary
.header
1301 print "\t" + GetThreadSummary(active_thread
)
1302 current_processor
= current_processor
.processor_list
1305 def GetFullBackTrace(frame_addr
, verbosity
= vHUMAN
, prefix
= ""):
1306 """ Get backtrace across interrupt context.
1307 params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7)
1308 prefix - str - prefix for each line of output.
1313 frame_ptr
= frame_addr
1314 previous_frame_ptr
= 0
1315 # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header
1316 mh_execute_addr
= int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16)
1317 while frame_ptr
and frame_ptr
!= previous_frame_ptr
and bt_count
< 128:
1318 if (not kern
.arch
.startswith('arm') and frame_ptr
< mh_execute_addr
) or (kern
.arch
.startswith('arm') and frame_ptr
> mh_execute_addr
):
1320 pc_val
= kern
.GetValueFromAddress(frame_ptr
+ kern
.ptrsize
,'uintptr_t *')
1321 pc_val
= unsigned(dereference(pc_val
))
1322 out_string
+= prefix
+ GetSourceInformationForAddress(pc_val
) + "\n"
1324 previous_frame_ptr
= frame_ptr
1325 frame_val
= kern
.GetValueFromAddress((frame_ptr
), 'uintptr_t *')
1326 if unsigned(frame_val
) == 0:
1328 frame_ptr
= unsigned(dereference(frame_val
))
1332 @lldb_command('fullbt')
1333 def FullBackTrace(cmd_args
=[]):
1334 """ Show full backtrace across the interrupt boundary.
1335 Syntax: fullbt <frame ptr>
1336 Example: fullbt `$rbp`
1338 if len(cmd_args
) < 1:
1339 print FullBackTrace
.__doc
__
1341 print GetFullBackTrace(ArgumentStringToInt(cmd_args
[0]), prefix
="\t")
1343 @lldb_command('fullbtall')
1344 def FullBackTraceAll(cmd_args
=[]):
1345 """ Show full backtrace across the interrupt boundary for threads running on all processors.
1349 for processor
in IterateLinkedList(kern
.globals.processor_list
, 'processor_list') :
1350 print "\n" + GetProcessorSummary(processor
)
1351 active_thread
= processor
.active_thread
1352 if unsigned(active_thread
) != 0 :
1353 task_val
= active_thread
.task
1354 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1355 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1356 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1357 print "\t" + GetThreadSummary
.header
1358 print "\t" + GetThreadSummary(active_thread
)
1359 print "\tBacktrace:"
1361 ThreadVal
= GetLLDBThreadForKernelThread(active_thread
)
1363 FramePtr
= ThreadVal
.frames
[0].GetFP()
1365 print GetFullBackTrace(unsigned(FramePtr
), prefix
="\t")
1368 @lldb_command('symbolicate')
1369 def SymbolicateAddress(cmd_args
=[]):
1370 """ Symbolicate an address for symbol information from loaded symbols
1371 Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr"
1373 if len(cmd_args
) < 1:
1374 print "Invalid address.\nSyntax: symbolicate <address>"
1376 print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args
[0]))
1379 @lldb_command('showinitchild')
1380 def ShowInitChild(cmd_args
=None):
1381 """ Routine to print out all processes in the system
1382 which are children of init process
1384 headp
= kern
.globals.initproc
.p_children
1385 for pp
in IterateListEntry(headp
, 'struct proc *', 'p_sibling'):
1386 print GetProcInfo(pp
)
1389 @lldb_command('showproctree')
1390 def ShowProcTree(cmd_args
=None):
1391 """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes.
1392 If no argument is given, showproctree will print all the processes in the system.
1393 If pid is specified, showproctree prints all the descendants of the indicated process
1397 search_pid
= ArgumentStringToInt(cmd_args
[0])
1400 print "pid specified must be a positive number"
1401 print ShowProcTree
.__doc
__
1404 hdr_format
= "{0: <6s} {1: <14s} {2: <9s}\n"
1405 out_string
= hdr_format
.format("PID", "PROCESS", "POINTER")
1406 out_string
+= hdr_format
.format('='*3, '='*7, '='*7)
1407 proc
= GetProcForPid(search_pid
)
1408 out_string
+= "{0: <6d} {1: <14s} [ {2: #019x} ]\n".format(proc
.p_ppid
, proc
.p_pptr
.p_comm
, unsigned(proc
.p_pptr
))
1409 out_string
+= "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(proc
.p_pid
, proc
.p_comm
, unsigned(proc
))
1411 ShowProcTreeRecurse(proc
, "| ")
1415 def ShowProcTreeRecurse(proc
, prefix
=""):
1416 """ Prints descendants of a given proc in hierarchial tree form
1418 proc : core.value representing a struct proc * in the kernel
1420 str : String containing info about a given proc and its descendants in tree form
1422 if proc
.p_childrencnt
> 0:
1423 head_ptr
= proc
.p_children
.lh_first
1425 for p
in IterateListEntry(proc
.p_children
, 'struct proc *', 'p_sibling'):
1426 print prefix
+ "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(p
.p_pid
, p
.p_comm
, unsigned(p
))
1427 ShowProcTreeRecurse(p
, prefix
+ "| ")
1429 @lldb_command('showthreadfortid')
1430 def ShowThreadForTid(cmd_args
=None):
1431 """ The thread structure contains a unique thread_id value for each thread.
1432 This command is used to retrieve the address of the thread structure(thread_t)
1433 corresponding to a given thread_id.
1436 print "Please provide thread_t whose tid you'd like to look up"
1437 print ShowThreadForTid
.__doc
__
1439 search_tid
= ArgumentStringToInt(cmd_args
[0])
1440 for taskp
in kern
.tasks
:
1441 for actp
in IterateQueue(taskp
.threads
, 'struct thread *', 'task_threads'):
1442 if search_tid
== int(actp
.thread_id
):
1443 print "Found {0: #019x}".format(actp
)
1444 print GetThreadSummary
.header
1445 print GetThreadSummary(actp
)
1447 print "Not a valid thread_id"
1449 def GetProcessorSummary(processor
):
1450 """ Internal function to print summary of processor
1451 params: processor - value representing struct processor *
1452 return: str - representing the details of given processor
1455 processor_state_str
= "INVALID"
1456 processor_state
= int(processor
.state
)
1458 processor_states
= {
1462 # 3 (formerly INACTIVE)
1468 if processor_state
in processor_states
:
1469 processor_state_str
= "{0: <11s} ".format(processor_states
[processor_state
])
1471 processor_recommended_str
= ""
1472 if int(processor
.is_recommended
) == 0:
1473 processor_recommended_str
= " (not recommended)"
1476 preemption_disable
= 0
1477 preemption_disable_str
= ""
1479 if kern
.arch
== 'x86_64':
1480 cpu_data
= kern
.globals.cpu_data_ptr
[processor
.cpu_id
]
1481 if (cpu_data
!= 0) :
1482 ast
= cpu_data
.cpu_pending_ast
1483 preemption_disable
= cpu_data
.cpu_preemption_level
1484 # On arm64, it's kern.globals.CpuDataEntries[processor.cpu_id].cpu_data_vaddr
1485 # but LLDB can't find CpuDataEntries...
1487 ast_str
= GetASTSummary(ast
)
1489 if (preemption_disable
!= 0) :
1490 preemption_disable_str
= "Preemption Disabled"
1492 out_str
= "Processor {: <#018x} cpu_id {:>#4x} AST: {:<6s} State {:<s}{:<s} {:<s}\n".format(
1493 processor
, int(processor
.cpu_id
), ast_str
, processor_state_str
, processor_recommended_str
,
1494 preemption_disable_str
)
1497 def GetLedgerEntrySummary(ledger_template
, ledger
, i
):
1498 """ Internal function to get internals of a ledger entry (*not* a ledger itself)
1499 params: ledger_template - value representing struct ledger_template_t for the task or thread
1500 ledger - value representing struct ledger_entry *
1501 return: str - formatted output information of ledger entries
1503 ledger_limit_infinity
= (uint64_t(0x1).value
<< 63) - 1
1504 lf_refill_scheduled
= 0x0400
1505 lf_tracking_max
= 0x4000
1508 now
= unsigned(kern
.globals.sched_tick
) / 20
1511 out_str
+= "{: >32s} {:<2d}:".format(ledger_template
.lt_entries
[i
].et_key
, i
)
1512 out_str
+= "{: >15d} ".format(unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
))
1513 if (ledger
.le_flags
& lf_tracking_max
):
1514 out_str
+= "{:9d} {:5d} ".format(ledger
._le
.le_maxtracking
.le_peaks
[0].le_max
, now
- unsigned(ledger
._le
.le_maxtracking
.le_peaks
[0].le_time
))
1518 if (ledger
.le_flags
& lf_tracking_max
):
1519 out_str
+= "{:12d} ".format(ledger
._le
.le_maxtracking
.le_lifetime_max
)
1522 out_str
+= "{:12d} {:12d} ".format(unsigned(ledger
.le_credit
), unsigned(ledger
.le_debit
))
1523 if (unsigned(ledger
.le_limit
) != ledger_limit_infinity
):
1524 out_str
+= "{:12d} ".format(unsigned(ledger
.le_limit
))
1528 if (ledger
.le_flags
& lf_refill_scheduled
):
1529 out_str
+= "{:15d} ".format(ledger
._le
.le_refill
.le_refill_period
)
1533 if (ledger
.le_flags
& lf_refill_scheduled
):
1534 out_str
+= "{:9d} ".format((unsigned(ledger
.le_limit
) * 100) / ledger
._le
.le_refill
.le_refill_period
)
1538 if (unsigned(ledger
.le_warn_level
) != ledger_limit_infinity
):
1539 out_str
+= "{:9d} ".format((unsigned(ledger
.le_warn_level
) * 100) / unsigned(ledger
.le_limit
))
1543 if ((unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
)) > unsigned(ledger
.le_limit
)):
1548 out_str
+= "{:#8x}\n".format(ledger
.le_flags
)
1551 def GetThreadLedgerSummary(thread_val
):
1552 """ Internal function to get a summary of ledger entries for the given thread
1553 params: thread - value representing struct thread *
1554 return: str - formatted output information for ledger entries of the input thread
1556 out_str
= " [{:#08x}]\n".format(thread_val
)
1557 ledgerp
= thread_val
.t_threadledger
1560 while i
!= ledgerp
.l_template
.lt_cnt
:
1561 out_str
+= GetLedgerEntrySummary(kern
.globals.thread_ledger_template
,
1562 ledgerp
.l_entries
[i
], i
)
1566 @header("{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >9s} {5: >6s} {6: >12s} {7: >11s} \
1567 {8: >7s} {9: >13s} {10: <15s} {11: <8s} {12: <9s} {13: <6s} {14: >6s}".format(
1568 "task [thread]", "entry", "#", "balance", "peakA", "(age)", "lifemax", "credit",
1569 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags"))
1570 def GetTaskLedgers(task_val
):
1571 """ Internal function to get summary of ledger entries from the task and its threads
1572 params: task_val - value representing struct task *
1573 return: str - formatted output information for ledger entries of the input task
1576 task_ledgerp
= task_val
.ledger
1578 out_str
+= "{: #08x} ".format(task_val
)
1579 pval
= Cast(task_val
.bsd_info
, 'proc *')
1581 out_str
+= "{: <5s}:\n".format(pval
.p_comm
)
1583 out_str
+= "Invalid process:\n"
1584 while i
!= task_ledgerp
.l_template
.lt_cnt
:
1585 out_str
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, task_ledgerp
.l_entries
[i
], i
)
1589 for thval
in IterateQueue(task_val
.threads
, 'thread *', 'task_threads'):
1590 out_str
+= GetThreadLedgerSummary(thval
)
1594 # Macro: showtaskledgers
1596 @lldb_command('showtaskledgers', 'F:')
1597 def ShowTaskLedgers(cmd_args
=None, cmd_options
={}):
1598 """ Routine to print a summary of ledger entries for the task and all of its threads
1599 Usage: showtaskledgers <address of task>
1600 or : showtaskledgers -F <name of task>
1602 if "-F" in cmd_options
:
1603 task_list
= FindTasksByName(cmd_options
["-F"])
1604 for tval
in task_list
:
1605 print GetTaskLedgers
.header
1606 print GetTaskLedgers(tval
)
1610 raise ArgumentError("No arguments passed.")
1611 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1613 raise ArgumentError("unknown arguments: %r" %cmd
_args
)
1614 print GetTaskLedgers
.header
1615 print GetTaskLedgers(tval
)
1617 # EndMacro: showtaskledgers
1619 # Macro: showalltaskledgers
1621 @lldb_command('showalltaskledgers')
1622 def ShowAllTaskLedgers(cmd_args
=None):
1623 """ Routine to print a summary of ledger entries for all tasks and respective threads
1624 Usage: showalltaskledgers
1626 for t
in kern
.tasks
:
1627 task_val
= unsigned(t
)
1628 ShowTaskLedgers([task_val
])
1630 # EndMacro: showalltaskledgers
1632 # Macro: showprocuuidpolicytable
1634 @lldb_type_summary(['proc_uuid_policy_entry'])
1635 @header("{0: <36s} {1: <10s}".format("uuid", "flags"))
1636 def GetProcUUIDPolicyEntrySummary(entry
):
1637 """ Summarizes the important fields in proc_uuid_policy_entry structure.
1638 params: entry: value - value object representing an entry
1639 returns: str - summary of the entry
1643 data
.append(int(entry
.uuid
[i
]))
1644 flags
= unsigned(entry
.flags
)
1645 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
)
1648 @lldb_command('showprocuuidpolicytable')
1649 def ShowProcUUIDPolicyTable(cmd_args
=None):
1650 """ Routine to print the proc UUID policy table
1651 Usage: showprocuuidpolicytable
1653 hashslots
= unsigned(kern
.globals.proc_uuid_policy_hash_mask
)
1654 print "{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary
.header
1655 for i
in range(0, hashslots
+1):
1656 headp
= addressof(kern
.globals.proc_uuid_policy_hashtbl
[i
])
1658 for entry
in IterateListEntry(headp
, 'struct proc_uuid_policy_entry *', 'entries'):
1659 print "{0: >2d}.{1: <5d} ".format(i
, entrynum
) + GetProcUUIDPolicyEntrySummary(entry
)
1663 # EndMacro: showprocuuidpolicytable
1665 @lldb_command('showalltaskpolicy')
1666 def ShowAllTaskPolicy(cmd_args
=None):
1668 Routine to print a summary listing of all the tasks
1669 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1670 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1671 io_policy -> RAGE - rapid aging of vnodes requested
1672 NORM - normal I/O explicitly requested (this is the default)
1673 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1674 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1677 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1678 for t
in kern
.tasks
:
1679 pval
= Cast(t
.bsd_info
, 'proc *')
1680 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1681 requested_strings
= [
1682 ["int_darwinbg", "DBG-int"],
1683 ["ext_darwinbg", "DBG-ext"],
1684 ["int_iotier", "iotier-int"],
1685 ["ext_iotier", "iotier-ext"],
1686 ["int_iopassive", "passive-int"],
1687 ["ext_iopassive", "passive-ext"],
1688 ["bg_iotier", "bg-iotier"],
1689 ["terminated", "terminated"],
1690 ["th_pidbind_bg", "bg-pidbind"],
1691 ["t_apptype", "apptype"],
1692 ["t_boosted", "boosted"],
1694 ["t_tal_enabled", "tal-enabled"],
1695 ["t_base_latency_qos", "latency-base"],
1696 ["t_over_latency_qos", "latency-override"],
1697 ["t_base_through_qos", "throughput-base"],
1698 ["t_over_through_qos", "throughput-override"]
1702 for value
in requested_strings
:
1703 if t
.requested_policy
.__getattr
__(value
[0]) :
1704 requested
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1708 suppression_strings
= [
1709 ["t_sup_active", "active"],
1710 ["t_sup_lowpri_cpu", "lowpri-cpu"],
1711 ["t_sup_timer", "timer-throttling"],
1712 ["t_sup_disk", "disk-throttling"],
1713 ["t_sup_cpu_limit", "cpu-limits"],
1714 ["t_sup_suspend", "suspend"],
1715 ["t_sup_bg_sockets", "bg-sockets"]
1719 for value
in suppression_strings
:
1720 if t
.requested_policy
.__getattr
__(value
[0]) :
1721 suppression
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1725 effective_strings
= [
1726 ["darwinbg", "background"],
1727 ["lowpri_cpu", "lowpri-cpu"],
1728 ["io_tier", "iotier"],
1729 ["io_passive", "passive"],
1730 ["all_sockets_bg", "bg-allsockets"],
1731 ["new_sockets_bg", "bg-newsockets"],
1732 ["bg_iotier", "bg-iotier"],
1733 ["terminated", "terminated"],
1734 ["t_gpu_deny", "gpu-deny"],
1735 ["t_tal_engaged", "tal-engaged"],
1736 ["t_suspended", "suspended"],
1737 ["t_watchers_bg", "bg-watchers"],
1738 ["t_latency_qos", "latency-qos"],
1739 ["t_through_qos", "throughput-qos"],
1740 ["t_sup_active", "suppression-active"],
1745 for value
in effective_strings
:
1746 if t
.effective_policy
.__getattr
__(value
[0]) :
1747 effective
+=value
[1] + ": " + str(t
.effective_policy
.__getattr
__(value
[0])) + " "
1751 print "requested: " + requested
1752 print "suppression: " + suppression
1753 print "effective: " + effective
1756 @lldb_type_summary(['wait_queue', 'wait_queue_t'])
1757 @header("{: <20s} {: <20s} {: <15s} {:<5s} {:<5s} {: <20s}".format("waitq", "interlock", "policy", "members", "threads", "eventmask"))
1758 def GetWaitQSummary(waitq
):
1759 """ Summarizes the important fields in task structure.
1760 params: task: value - value object representing a task in kernel
1761 returns: str - summary of the task
1764 format_string
= '{: <#020x} {: <#020x} {: <15s} {: <5d} {: <5d} {: <#020x}'
1768 if (waitq
.wq_fifo
== 1) :
1773 if (waitq
.wq_prepost
== 1) :
1776 if (waitq
.wq_type
== 0x3) :
1778 elif (waitq
.wq_type
== 0x2) :
1783 out_string
+= format_string
.format(waitq
, unsigned(waitq
.wq_interlock
.lock_data
), policy
, 0, 0, unsigned(waitq
.wq_eventmask
))
1785 out_string
+= "\n" + GetThreadSummary
.header
1787 for thread
in IterateQueue(waitq
.wq_queue
, "thread_t", "links"):
1788 out_string
+= "\n" + GetThreadSummary(thread
)
1793 @lldb_command('showallsuspendedtasks', '')
1794 def ShowSuspendedTasks(cmd_args
=[], options
={}):
1795 """ Show a list of suspended tasks with their process name summary.
1797 print GetTaskSummary
.header
+ ' ' + GetProcSummary
.header
1798 for t
in kern
.tasks
:
1799 if t
.suspend_count
> 0:
1800 print GetTaskSummary(t
) + ' ' + GetProcSummary(Cast(t
.bsd_info
, 'proc *'))
1804 @lldb_command('showallpte')
1805 def ShowAllPte(cmd_args
=None):
1806 """ Prints out the physical address of the pte for all tasks
1808 head_taskp
= addressof(kern
.globals.tasks
)
1809 taskp
= Cast(head_taskp
.next
, 'task *')
1810 while taskp
!= head_taskp
:
1811 procp
= Cast(taskp
.bsd_info
, 'proc *')
1812 out_str
= "task = {:#x} pte = {:#x}\t".format(taskp
, taskp
.map.pmap
.ttep
)
1814 out_str
+= "{:s}\n".format(procp
.p_comm
)
1818 taskp
= Cast(taskp
.tasks
.next
, 'struct task *')
1820 # EndMacro: showallpte
1822 # Macro: showallrefcounts
1823 @lldb_command('showallrefcounts')
1824 @header("{0: <20s} {1: ^10s}".format("task", "ref_count"))
1825 def ShowAllRefCounts(cmd_args
=None):
1826 """ Prints the ref_count of all tasks
1829 head_taskp
= addressof(kern
.globals.tasks
)
1830 taskp
= Cast(head_taskp
.next
, 'task *')
1831 print ShowAllRefCounts
.header
1832 while taskp
!= head_taskp
:
1833 out_str
+= "{: <#20x}".format(taskp
)
1834 out_str
+= "{: ^10d}\n".format(taskp
.ref_count
)
1835 taskp
= Cast(taskp
.tasks
.next
, 'task *')
1837 # EndMacro: showallrefcounts
1839 # Macro: showallrunnablethreads
1840 @lldb_command('showallrunnablethreads')
1841 def ShowAllRunnableThreads(cmd_args
=None):
1842 """ Prints the sched usage information for all threads of each task
1845 for taskp
in kern
.tasks
:
1846 for actp
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'):
1847 if int(actp
.state
& 0x4):
1848 ShowActStack([unsigned(actp
)])
1850 # EndMacro: showallrunnablethreads
1852 # Macro: showallschedusage
1853 @lldb_command('showallschedusage')
1854 @header("{0:<20s} {1:^10s} {2:^10s} {3:^15s}".format("Thread", "Priority", "State", "sched_usage"))
1855 def ShowAllSchedUsage(cmd_args
=None):
1856 """ Prints the sched usage information for all threads of each task
1859 for taskp
in kern
.tasks
:
1860 ShowTask([unsigned(taskp
)])
1861 print ShowAllSchedUsage
.header
1862 for actp
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'):
1863 out_str
= "{: <#20x}".format(actp
)
1864 out_str
+= "{: ^10s}".format(str(int(actp
.sched_pri
)))
1865 state
= int(actp
.state
)
1866 thread_state_chars
= {0:'', 1:'W', 2:'S', 4:'R', 8:'U', 16:'H', 32:'A', 64:'P', 128:'I'}
1868 state_str
+= thread_state_chars
[int(state
& 0x1)]
1869 state_str
+= thread_state_chars
[int(state
& 0x2)]
1870 state_str
+= thread_state_chars
[int(state
& 0x4)]
1871 state_str
+= thread_state_chars
[int(state
& 0x8)]
1872 state_str
+= thread_state_chars
[int(state
& 0x10)]
1873 state_str
+= thread_state_chars
[int(state
& 0x20)]
1874 state_str
+= thread_state_chars
[int(state
& 0x40)]
1875 state_str
+= thread_state_chars
[int(state
& 0x80)]
1876 out_str
+= "{: ^10s}".format(state_str
)
1877 out_str
+= "{: >15d}".format(actp
.sched_usage
)
1878 print out_str
+ "\n"
1881 # EndMacro: showallschedusage
1883 #Macro: showprocfilessummary
1884 @lldb_command('showprocfilessummary')
1885 @header("{0: <20s} {1: <20s} {2: >10s}".format("Process", "Name", "Number of Open Files"))
1886 def ShowProcFilesSummary(cmd_args
=None):
1887 """ Display the summary of open file descriptors for all processes in task list
1888 Usage: showprocfilessummary
1890 print ShowProcFilesSummary
.header
1891 for proc
in kern
.procs
:
1892 proc_filedesc
= proc
.p_fd
1893 proc_ofiles
= proc_filedesc
.fd_ofiles
1894 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
1897 if proc_filedesc
.fd_nfiles
!= 0:
1898 while count
<= proc_lastfile
:
1899 if unsigned(proc_ofiles
[count
]) != 0:
1900 proc_file_count
+= 1
1902 print "{0: <#020x} {1: <20s} {2: >10d}".format(proc
, proc
.p_comm
, proc_file_count
)
1904 #EndMacro: showprocfilessummary
1906 @lldb_command('workinguserstacks')
1907 def WorkingUserStacks(cmd_args
=None):
1908 """ Print out the user stack for each thread in a task, followed by the user libraries.
1909 Syntax: (lldb) workinguserstacks <task_t>
1912 print "Insufficient arguments" + ShowTaskUserStacks
.__doc
__
1914 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1915 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1916 pval
= Cast(task
.bsd_info
, 'proc *')
1917 print GetTaskSummary(task
) + " " + GetProcSummary(pval
) + "\n \n"
1918 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1919 print "For thread 0x{0:x}".format(thval
)
1921 ShowThreadUserStack([hex(thval
)])
1922 except Exception as exc_err
:
1923 print "Failed to show user stack for thread 0x{0:x}".format(thval
)
1927 print "Enable debugging ('(lldb) xnudebug debug') to see detailed trace."
1928 WorkingUserLibraries([hex(task
)])
1931 @static_var("exec_load_path", 0)
1932 @lldb_command("workingkuserlibraries")
1933 def WorkingUserLibraries(cmd_args
=None):
1934 """ Show binary images known by dyld in target task
1935 For a given user task, inspect the dyld shared library state and print information about all Mach-O images.
1936 Syntax: (lldb)workinguserlibraries <task_t>
1939 print "Insufficient arguments"
1940 print ShowTaskUserLibraries
.__doc
__
1943 print "{0: <18s} {1: <12s} {2: <36s} {3: <50s}".format('address','type','uuid','path')
1944 out_format
= "0x{0:0>16x} {1: <12s} {2: <36s} {3: <50s}"
1945 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task_t')
1946 is_task_64
= int(task
.t_flags
) & 0x1
1947 dyld_all_image_infos_address
= unsigned(task
.all_image_info_addr
)
1949 if dyld_all_image_infos_address
== 0:
1950 print "No dyld shared library information available for task"
1952 vers_info_data
= GetUserDataAsString(task
, dyld_all_image_infos_address
, 112)
1953 version
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t")
1954 cur_data_offset
+= 4
1956 print "Unknown dyld all_image_infos version number %d" % version
1957 image_info_count
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t")
1958 WorkingUserLibraries
.exec_load_path
= 0
1960 image_info_size
= 24
1961 image_info_array_address
= _ExtractDataFromString(vers_info_data
, 8, "uint64_t")
1962 dyld_load_address
= _ExtractDataFromString(vers_info_data
, 8*4, "uint64_t")
1963 dyld_all_image_infos_address_from_struct
= _ExtractDataFromString(vers_info_data
, 8*13, "uint64_t")
1965 image_info_size
= 12
1966 image_info_array_address
= _ExtractDataFromString(vers_info_data
, 4*2, "uint32_t")
1967 dyld_load_address
= _ExtractDataFromString(vers_info_data
, 4*5, "uint32_t")
1968 dyld_all_image_infos_address_from_struct
= _ExtractDataFromString(vers_info_data
, 4*14, "uint32_t")
1969 # Account for ASLR slide before dyld can fix the structure
1970 dyld_load_address
= dyld_load_address
+ (dyld_all_image_infos_address
- dyld_all_image_infos_address_from_struct
)
1973 while i
< image_info_count
:
1974 image_info_address
= image_info_array_address
+ i
* image_info_size
1975 img_data
= GetUserDataAsString(task
, image_info_address
, image_info_size
)
1977 image_info_addr
= _ExtractDataFromString(img_data
, 0, "uint64_t")
1978 image_info_path
= _ExtractDataFromString(img_data
, 8, "uint64_t")
1980 image_info_addr
= _ExtractDataFromString(img_data
, 0, "uint32_t")
1981 image_info_path
= _ExtractDataFromString(img_data
, 4, "uint32_t")
1982 PrintImageInfo(task
, image_info_addr
, image_info_path
)
1985 # load_path might get set when the main executable is processed.
1986 if WorkingUserLibraries
.exec_load_path
!= 0:
1987 PrintImageInfo(task
, dyld_load_address
, WorkingUserLibraries
.exec_load_path
)
1990 # Macro: showstackaftertask
1991 @lldb_command('showstackaftertask','F:')
1992 def Showstackaftertask(cmd_args
=None,cmd_options
={}):
1993 """ Routine to print the thread stacks for all tasks succeeding a given task
1994 Usage: showstackaftertask <0xaddress of task>
1995 or: showstackaftertask -F <taskname>
1997 if "-F" in cmd_options
:
1998 # Find the task pointer corresponding to its task name
1999 find_task_str
= cmd_options
["-F"]
2000 task_list
= FindTasksByName(find_task_str
)
2002 # Iterate through the list of tasks and print all task stacks thereafter
2003 for tval
in task_list
:
2004 ListTaskStacks(tval
)
2008 raise ArgumentError("Insufficient arguments")
2009 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
2011 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
2013 ListTaskStacks(tval
)
2017 # EndMacro: showstackaftertask
2019 def ListTaskStacks(task
):
2020 """ Search for a given task and print the list of all task stacks thereafter.
2022 # Initialize local variable task_flag to mark when a given task is found.
2025 for t
in kern
.tasks
:
2026 if (task_flag
== 1):
2032 # Macro: showstackafterthread
2033 @lldb_command('showstackafterthread')
2034 def Showstackafterthread(cmd_args
= None):
2035 """ Routine to print the stacks of all threads succeeding a given thread.
2036 Usage: Showstackafterthread <0xaddress of thread>
2038 # local variable thread_flag is used to mark when a given thread is found.
2041 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
2043 raise ArgumentError("No arguments passed")
2044 # Iterate through list of all tasks to look up a given thread
2045 for t
in kern
.tasks
:
2047 pval
= Cast(t
.bsd_info
, 'proc *')
2048 print GetTaskSummary
.header
+ " "+ GetProcSummary
.header
2049 print GetTaskSummary(t
) + " "+ GetProcSummary(pval
)
2051 # Look up for a given thread from the the list of threads of a given task
2052 for thval
in IterateQueue(t
.threads
, 'thread *', 'task_threads'):
2053 if (thread_flag
==1):
2055 print " " + GetThreadSummary
.header
2056 print " " + GetThreadSummary(thval
)
2057 print GetThreadBackTrace(thval
, prefix
="\t")+"\n"
2060 if(thval
==threadval
):
2061 pval
= Cast(t
.bsd_info
, 'proc *')
2062 process_name
= "{:s}".format(pval
.p_comm
)
2064 print " *** Continuing to dump the thread stacks from the process *** :" + " " + process_name