""" Please make sure you read the README file COMPLETELY BEFORE reading anything below.
- It is very critical that you read coding guidelines in Section E in README file.
+ It is very critical that you read coding guidelines in Section E in README file.
"""
from xnu import *
import sys, shlex
from utils import *
from core.lazytarget import *
+import time
import xnudefines
+def GetProcNameForTask(task):
+ """ returns a string name of the process. if proc is not valid "unknown" is returned
+ params:
+ task: value object represeting a task in the kernel.
+ returns:
+ str : A string name of the process linked to the task
+ """
+ if not task or not unsigned(task.bsd_info):
+ return "unknown"
+ p = Cast(task.bsd_info, 'proc *')
+ return str(p.p_comm)
+
+def GetProcPIDForTask(task):
+ """ returns a int pid of the process. if the proc is not valid, val[5] from audit_token is returned.
+ params:
+ task: value object representing a task in the kernel
+ returns:
+ int : pid of the process or -1 if not found
+ """
+ if task and unsigned(task.bsd_info):
+ p = Cast(task.bsd_info, 'proc *')
+ return unsigned(p.p_pid)
+
+ if task :
+ return unsigned(task.audit_token.val[5])
+
+ return -1
+
def GetProcInfo(proc):
""" returns a string name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields.
params:
params:
cmd_args - [] : array of strings passed from lldb command prompt
"""
- for proc in kern.zombprocs:
- print GetProcInfo(proc)
+ if len(kern.zombprocs) != 0:
+ print "\nZombie Processes:"
+ for proc in kern.zombprocs:
+ print GetProcInfo(proc) + "\n\n"
+
+@lldb_command('zombtasks')
+def ZombTasks(cmd_args=None):
+ """ Routine to print out all tasks in the zombie list
+ params: None
+ """
+ out_str = ""
+ if len(kern.zombprocs) != 0:
+ header = "\nZombie Tasks:\n"
+ header += GetTaskSummary.header + " " + GetProcSummary.header
+ for proc in kern.zombprocs:
+ if proc.p_stat != 5:
+ t = Cast(proc.task, 'task *')
+ out_str += GetTaskSummary(t) +" "+ GetProcSummary(proc) + "\n"
+ if out_str != "":
+ print header
+ print out_str
@lldb_command('zombstacks')
def ZombStacks(cmd_args=None):
""" Routine to print out all stacks of tasks that are exiting
"""
+ header_flag = 0
for proc in kern.zombprocs:
if proc.p_stat != 5:
+ if header_flag == 0:
+ print "\nZombie Stacks:"
+ header_flag = 1
t = Cast(proc.task, 'task *')
ShowTaskStacks(t)
#End of Zombstacks
+def GetASTSummary(ast):
+ """ Summarizes an AST field
+ Flags:
+ P - AST_PREEMPT
+ Q - AST_QUANTUM
+ U - AST_URGENT
+ H - AST_HANDOFF
+ Y - AST_YIELD
+ A - AST_APC
+ L - AST_LEDGER
+ B - AST_BSD
+ K - AST_KPERF
+ M - AST_MACF
+ C - AST_CHUD
+ C - AST_CHUD_URGENT
+ G - AST_GUARD
+ T - AST_TELEMETRY_USER
+ T - AST_TELEMETRY_KERNEL
+ T - AST_TELEMETRY_WINDOWED
+ S - AST_SFI
+ """
+ out_string = ""
+ state = int(ast)
+ thread_state_chars = {0x0:'', 0x1:'P', 0x2:'Q', 0x4:'U', 0x8:'H', 0x10:'Y', 0x20:'A',
+ 0x40:'L', 0x80:'B', 0x100:'K', 0x200:'M', 0x400:'C', 0x800:'C',
+ 0x1000:'G', 0x2000:'T', 0x4000:'T', 0x8000:'T', 0x10000:'S'}
+ state_str = ''
+ mask = 0x1
+ while mask <= 0x10000:
+ state_str += thread_state_chars[int(state & mask)]
+ mask = mask << 1
+
+ return state_str
+
+
+@lldb_type_summary(['kcdata_descriptor *', 'kcdata_descriptor_t'])
+@header("{0: <20s} {1: <20s} {2: <20s} {3: <10s} {4: <5s}".format("kcdata_descriptor", "begin_addr", "cur_pos", "size", "flags"))
+def GetKCDataSummary(kcdata):
+ """ Summarizes kcdata_descriptor structure
+ params: kcdata: value - value object representing kcdata_descriptor
+ returns: str - summary of the kcdata object
+ """
+ format_string = "{0: <#020x} {1: <#020x} {2: <#020x} {3: <10d} {4: <#05x}"
+ return format_string.format(kcdata, kcdata.kcd_addr_begin, kcdata.kcd_addr_end, kcdata.kcd_length, kcdata.kcd_flags)
+
+
@lldb_type_summary(['task', 'task_t'])
@header("{0: <20s} {1: <20s} {2: <20s} {3: >5s} {4: <5s}".format("task","vm_map", "ipc_space", "#acts", "flags"))
-def GetTaskSummary(task):
+def GetTaskSummary(task, showcorpse=False):
""" Summarizes the important fields in task structure.
params: task: value - value object representing a task in kernel
returns: str - summary of the task
task_flags += 'P'
if hasattr(task, "suspend_count") and int(task.suspend_count) > 0:
task_flags += 'S'
- if hasattr(task, "imp_receiver") and int(task.imp_receiver) == 1:
- task_flags += 'R'
- if hasattr(task, "imp_donor") and int(task.imp_donor) == 1:
- task_flags += 'D'
- if hasattr(task, "task_imp_assertcnt") and int(task.task_imp_assertcnt) > 0:
- task_flags += 'B'
+ if hasattr(task, 'task_imp_base') and unsigned(task.task_imp_base):
+ tib = task.task_imp_base
+ if int(tib.iit_receiver) == 1:
+ task_flags += 'R'
+ if int(tib.iit_donor) == 1:
+ task_flags += 'D'
+ if int(tib.iit_assertcnt) > 0:
+ task_flags += 'B'
+
+ # check if corpse flag is set
+ if unsigned(task.t_flags) & 0x20:
+ task_flags += 'C'
+ if unsigned(task.t_flags) & 0x40:
+ task_flags += 'P'
+
out_string += format_string.format(task, task.map, task.itk_space, thread_count, task_flags)
+ if showcorpse is True and unsigned(task.corpse_info) != 0:
+ out_string += " " + GetKCDataSummary(task.corpse_info)
return out_string
@lldb_type_summary(['thread *', 'thread_t'])
-@header("{0: <24s} {1: <10s} {2: <20s} {3: <6s} {4: <10s} {5: <5s} {6: <20s} {7: <45s} {8: <20s} {9: <20s}".format('thread', 'thread_id', 'processor', 'pri', 'io_policy', 'state', 'wait_queue', 'wait_event', 'wmesg', 'thread_name'))
+@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'))
def GetThreadSummary(thread):
""" Summarize the thread structure. It decodes the wait state and waitevents from the data in the struct.
params: thread: value - value objecte representing a thread in kernel
returns: str - summary of a thread
+
+ State flags:
+ W - WAIT
+ S - SUSP
+ R - RUN
+ U - Uninterruptible
+ H - Terminated
+ A - Terminated and on termination queue
+ I - Idle thread
+ C - Crashed thread
+
+ policy flags:
+ B - darwinbg
+ L - lowpri cpu
+ T - IO throttle
+ P - IO passive
+ D - Terminated
"""
out_string = ""
- format_string = "{0: <24s} {1: <10s} {2: <20s} {3: <6s} {4: <10s} {5: <5s} {6: <20s} {7: <45s} {8: <20s} {9: <20s}"
+ 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}"
thread_ptr_str = str("{0: <#020x}".format(thread))
if int(thread.static_param) :
thread_ptr_str+="[WQ]"
thread_id = hex(thread.thread_id)
thread_name = ''
processor = hex(thread.last_processor)
+ base_priority = str(int(thread.base_pri))
sched_priority = str(int(thread.sched_pri))
+ sched_mode = ''
+ mode = str(thread.sched_mode)
+ if "TIMESHARE" in mode:
+ sched_mode+="timeshare"
+ elif "FIXED" in mode:
+ sched_mode+="fixed"
+ elif "REALTIME" in mode:
+ sched_mode+="realtime"
+
+ if (unsigned(thread.bound_processor) != 0):
+ sched_mode+=" bound"
+
+ # TH_SFLAG_THROTTLED
+ if (unsigned(thread.sched_flags) & 0x0004):
+ sched_mode+=" BG"
io_policy_str = ""
if int(thread.uthread) != 0:
io_policy_str += "D"
state = int(thread.state)
- thread_state_chars = {0:'', 1:'W', 2:'S', 4:'R', 8:'U', 16:'H', 32:'A', 64:'P', 128:'I'}
+ thread_state_chars = {0x0:'', 0x1:'W', 0x2:'S', 0x4:'R', 0x8:'U', 0x10:'H', 0x20:'A', 0x40:'P', 0x80:'I'}
state_str = ''
- state_str += thread_state_chars[int(state & 0x1)]
- state_str += thread_state_chars[int(state & 0x2)]
- state_str += thread_state_chars[int(state & 0x4)]
- state_str += thread_state_chars[int(state & 0x8)]
- state_str += thread_state_chars[int(state & 0x10)]
- state_str += thread_state_chars[int(state & 0x20)]
- state_str += thread_state_chars[int(state & 0x40)]
- state_str += thread_state_chars[int(state & 0x80)]
+ mask = 0x1
+ while mask <= 0x80 :
+ state_str += thread_state_chars[int(state & mask)]
+ mask = mask << 1
+
+ if int(thread.inspection):
+ state_str += 'C'
+
+ ast = int(thread.ast) | int(thread.reason)
+ ast_str = GetASTSummary(ast)
#wait queue information
wait_queue_str = ''
wait_message = ''
if ( state & 0x1 ) != 0:
#we need to look at the waitqueue as well
- wait_queue_str = str("{0: <#020x}".format(int(hex(thread.wait_queue), 16)))
+ wait_queue_str = str("{0: <#020x}".format(int(hex(thread.waitq), 16)))
wait_event_str = str("{0: <#020x}".format(int(hex(thread.wait_event), 16)))
wait_event_str_sym = kern.Symbolicate(int(hex(thread.wait_event), 16))
if len(wait_event_str_sym) > 0:
if int(uthread.uu_wmesg) != 0:
wait_message = str(Cast(uthread.uu_wmesg, 'char *'))
- out_string += format_string.format(thread_ptr_str, thread_id, processor, sched_priority, io_policy_str, state_str, wait_queue_str, wait_event_str, wait_message, thread_name )
+ 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)
return out_string
-
-@lldb_type_summary(['proc'])
+def GetTaskRoleString(role):
+ role_strs = {
+ 0 : "TASK_UNSPECIFIED",
+ 1 : "TASK_FOREGROUND_APPLICATION",
+ 2 : "TASK_BACKGROUND_APPLICATION",
+ 3 : "TASK_CONTROL_APPLICATION",
+ 4 : "TASK_GRAPHICS_SERVER",
+ 5 : "TASK_THROTTLE_APPLICATION",
+ 6 : "TASK_NONUI_APPLICATION",
+ 7 : "TASK_DEFAULT_APPLICATION",
+ }
+ return role_strs[int(role)]
+
+def GetCoalitionFlagString(coal):
+ flags = []
+ if (coal.privileged):
+ flags.append('privileged')
+ if (coal.termrequested):
+ flags.append('termrequested')
+ if (coal.terminated):
+ flags.append('terminated')
+ if (coal.reaped):
+ flags.append('reaped')
+ if (coal.notified):
+ flags.append('notified')
+ return "|".join(flags)
+
+def GetCoalitionTasks(queue, coal_type, thread_details=False):
+ sfi_strs = {
+ 0x0 : "SFI_CLASS_UNSPECIFIED",
+ 0x1 : "SFI_CLASS_DARWIN_BG",
+ 0x2 : "SFI_CLASS_APP_NAP",
+ 0x3 : "SFI_CLASS_MANAGED_FOCAL",
+ 0x4 : "SFI_CLASS_MANAGED_NONFOCAL",
+ 0x5 : "SFI_CLASS_DEFAULT_FOCAL",
+ 0x6 : "SFI_CLASS_DEFAULT_NONFOCAL",
+ 0x7 : "SFI_CLASS_KERNEL",
+ 0x8 : "SFI_CLASS_OPTED_OUT",
+ 0x9 : "SFI_CLASS_UTILITY",
+ 0xA : "SFI_CLASS_LEGACY_FOCAL",
+ 0xB : "SFI_CLASS_LEGACY_NONFOCAL",
+ 0xC : "SFI_CLASS_USER_INITIATED_FOCAL",
+ 0xD : "SFI_CLASS_USER_INITIATED_NONFOCAL",
+ 0xE : "SFI_CLASS_USER_INTERACTIVE_FOCAL",
+ 0xF : "SFI_CLASS_USER_INTERACTIVE_NONFOCAL",
+ 0x10 : "SFI_CLASS_MAINTENANCE",
+ }
+ tasks = []
+ field_name = 'task_coalition'
+ for task in IterateLinkageChain(queue, 'task *', field_name, coal_type * sizeof('queue_chain_t')):
+ task_str = "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(task),task,GetProcNameForTask(task),GetTaskRoleString(task.effective_policy.t_role))
+ if thread_details:
+ for thread in IterateQueue(task.threads, "thread_t", "task_threads"):
+ task_str += "\n\t\t\t|-> thread:" + hex(thread) + ", " + sfi_strs[int(thread.sfi_class)]
+ tasks.append(task_str)
+ return tasks
+
+def GetCoalitionTypeString(type):
+ """ Convert a coalition type field into a string
+ Currently supported types (from <mach/coalition.h>):
+ COALITION_TYPE_RESOURCE
+ COALITION_TYPE_JETSAM
+ """
+ if type == 0: # COALITION_TYPE_RESOURCE
+ return 'RESOURCE'
+ if type == 1:
+ return 'JETSAM'
+ return '<unknown>'
+
+def GetResourceCoalitionSummary(coal, verbose=False):
+ """ Summarize a resource coalition
+ """
+ out_string = "Resource Coalition:\n\t Ledger:\n"
+ thread_details = False
+ if config['verbosity'] > vSCRIPT:
+ thread_details = True
+ ledgerp = coal.r.ledger
+ if verbose and unsigned(ledgerp) != 0:
+ i = 0
+ while i != ledgerp.l_template.lt_cnt:
+ out_string += "\t\t"
+ out_string += GetLedgerEntrySummary(kern.globals.task_ledger_template, ledgerp.l_entries[i], i)
+ i = i + 1
+ 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)
+ 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)
+ 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)
+ out_string += "\n\t Tasks:\n\t\t"
+ tasks = GetCoalitionTasks(addressof(coal.r.tasks), 0, thread_details)
+ out_string += "\n\t\t".join(tasks)
+ return out_string
+
+def GetJetsamCoalitionSummary(coal, verbose=False):
+ out_string = "Jetsam Coalition:"
+ thread_details = False
+ if config['verbosity'] > vSCRIPT:
+ thread_details = True
+ if unsigned(coal.j.leader) == 0:
+ out_string += "\n\t NO Leader!"
+ else:
+ out_string += "\n\t Leader:\n\t\t"
+ 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))
+ out_string += "\n\t Extensions:\n\t\t"
+ tasks = GetCoalitionTasks(addressof(coal.j.extensions), 1, thread_details)
+ out_string += "\n\t\t".join(tasks)
+ out_string += "\n\t XPC Services:\n\t\t"
+ tasks = GetCoalitionTasks(addressof(coal.j.services), 1, thread_details)
+ out_string += "\n\t\t".join(tasks)
+ out_string += "\n\t Other Tasks:\n\t\t"
+ tasks = GetCoalitionTasks(addressof(coal.j.other), 1, thread_details)
+ out_string += "\n\t\t".join(tasks)
+ return out_string
+
+@lldb_type_summary(['coalition_t', 'coalition *'])
+@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"))
+def GetCoalitionSummary(coal):
+ if unsigned(coal) == 0:
+ return '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'.format(0, "", -1, -1, -1, -1, -1, "")
+ out_string = ""
+ format_string = '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'
+ type_string = GetCoalitionTypeString(coal.type)
+ flag_string = GetCoalitionFlagString(coal)
+ 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)
+ return out_string
+
+def GetCoalitionInfo(coal, verbose=False):
+ """ returns a string describing a coalition, including details about the particular coalition type.
+ params:
+ coal : value object representing a coalition in the kernel
+ returns:
+ str : A string describing the coalition.
+ """
+ if unsigned(coal) == 0:
+ return "<null coalition>"
+ typestr = GetCoalitionTypeString(coal.type)
+ flagstr = GetCoalitionFlagString(coal)
+ out_string = ""
+ 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)
+ if coal.type == 0: # COALITION_TYPE_RESOURCE
+ out_string += GetResourceCoalitionSummary(coal, verbose)
+ elif coal.type == 1: # COALITION_TYPE_JETSAM
+ out_string += GetJetsamCoalitionSummary(coal, verbose)
+ else:
+ out_string += "Unknown Type"
+
+ return out_string
+
+# Macro: showcoalitioninfo
+
+@lldb_command('showcoalitioninfo')
+def ShowCoalitionInfo(cmd_args=None, cmd_options={}):
+ """ Display more detailed information about a coalition
+ Usage: showcoalitioninfo <address of coalition>
+ """
+ verbose = False
+ if config['verbosity'] > vHUMAN:
+ verbose = True
+ if not cmd_args:
+ print "No arguments passed"
+ print ShowCoalitionInfo.__doc__
+ return False
+ coal = kern.GetValueFromAddress(cmd_args[0], 'coalition *')
+ if not coal:
+ print "unknown arguments:", str(cmd_args)
+ return False
+ print GetCoalitionInfo(coal, verbose)
+
+# EndMacro: showcoalitioninfo
+
+# Macro: showallcoalitions
+
+@lldb_command('showallcoalitions')
+def ShowAllCoalitions(cmd_args=None):
+ """ Print a summary listing of all the coalitions
+ """
+ global kern
+ print GetCoalitionSummary.header
+ for c in kern.coalitions:
+ print GetCoalitionSummary(c)
+
+# EndMacro: showallcoalitions
+
+# Macro: showtaskcoalitions
+
+@lldb_command('showtaskcoalitions', 'F:')
+def ShowTaskCoalitions(cmd_args=None, cmd_options={}):
+ """
+ """
+ task_list = []
+ if "-F" in cmd_options:
+ task_list = FindTasksByName(cmd_options["-F"])
+ elif cmd_args:
+ t = kern.GetValueFromAddress(cmd_args[0], 'task *')
+ task_list.append(t)
+ else:
+ raise ArgumentError("No arguments passed")
+
+ if len(task_list) > 0:
+ print GetCoalitionSummary.header
+ for task in task_list:
+ print GetCoalitionSummary(task.coalition[0])
+ print GetCoalitionSummary(task.coalition[1])
+
+# EndMacro: showtaskcoalitions
+
+@lldb_type_summary(['proc', 'proc *'])
@header("{0: >6s} {1: ^20s} {2: >14s} {3: ^10s} {4: <20s}".format("pid", "process", "io_policy", "wq_state", "command"))
def GetProcSummary(proc):
""" Summarize the process data.
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)
return out_string
+@lldb_type_summary(['tty_dev_t', 'tty_dev_t *'])
+@header("{0: <20s} {1: <10s} {2: <10s} {3: <15s} {4: <15s} {5: <15s} {6: <15s}".format("tty_dev","master", "slave", "open", "free", "name", "revoke"))
+def GetTTYDevSummary(tty_dev):
+ """ Summarizes the important fields in tty_dev_t structure.
+ params: tty_dev: value - value object representing a tty_dev_t in kernel
+ returns: str - summary of the tty_dev
+ """
+ out_string = ""
+ format_string = "{0: <#020x} {1: <#010x} {2: <#010x} {3: <15s} {4: <15s} {5: <15s} {6: <15s}"
+ open_fn = kern.Symbolicate(int(hex(tty_dev.open), 16))
+ free_fn = kern.Symbolicate(int(hex(tty_dev.free), 16))
+ name_fn = kern.Symbolicate(int(hex(tty_dev.name), 16))
+ revoke_fn = kern.Symbolicate(int(hex(tty_dev.revoke), 16))
+ out_string += format_string.format(tty_dev, tty_dev.master, tty_dev.slave, open_fn, free_fn, name_fn, revoke_fn)
+ return out_string
+
+@lldb_type_summary(['kqueue *'])
+@header("{: <20s} {: <20s} {: <6s} {: <20s} {: <10s}".format('kqueue', 'process', '#events', 'wqs', 'state'))
+def GetKQueueSummary(kq):
+ """ summarizes kqueue information
+ returns: str - summary of kqueue
+ """
+ out_string = ""
+ format_string = "{o: <#020x} {o.kq_p: <#020x} {o.kq_count: <6d} {o.kq_wqs: <#020x} {st_str: <10s}"
+ state = int(kq.kq_state)
+ state_str = ''
+ mask = 0x1
+ while mask <= 0x80 :
+ if int(state & mask):
+ state_str += ' ' + xnudefines.kq_state_strings[int(state & mask)]
+ mask = mask << 1
+ out_string += format_string.format(o=kq, st_str=state_str)
+ out_string += "\n" + GetKnoteSummary.header
+ for kn in IterateTAILQ_HEAD(kq.kq_head, 'kn_tqe'):
+ out_string += "\n" + GetKnoteSummary(kn)
+ return out_string
+
+@lldb_type_summary(['knote *'])
+@header("{0: <20s} {1: <10s} {2: <10s} {3: <20s} {4: <20s} {5: <30s}".format('knote', 'ident', 'kev_flags', 'kn_kq', 'filtops', ' status'))
+def GetKnoteSummary(kn):
+ """ Summarizes a knote and related information
+ returns: str - summary of knote
+ """
+ out_string = ""
+ format_string = "{o: <#020x} {o.kn_kevent.ident: <#010X} {o.kn_kevent.flags: <#010X} {o.kn_kq: <#020X} {ops_str: <20s} {st_str: <30s}"
+ state = unsigned(kn.kn_status)
+ fops_str = kern.Symbolicate(unsigned(kn.kn_fop))
+ mask = 0x1
+ status_desc = ''
+ while mask <= 0x40:
+ if state & mask:
+ status_desc += ' ' + xnudefines.kn_state_strings[int(state & mask)]
+ mask = mask << 1
+
+ out_string += format_string.format(o=kn, st_str=status_desc, ops_str=fops_str)
+ return out_string
+
# Macro: showtask
@lldb_command('showtask', 'F:')
#EndMacro: showprocfiles
+
+def GetProcKqueues(proc):
+ filetype_KQUEUE = 5
+
+ proc_filedesc = proc.p_fd
+ proc_lastfile = unsigned(proc_filedesc.fd_lastfile)
+ proc_ofiles = proc_filedesc.fd_ofiles
+
+ queues = list()
+
+ if unsigned(proc_ofiles) == 0:
+ return queues
+
+ count = 0
+
+ while count <= proc_lastfile:
+ if unsigned(proc_ofiles[count]) != 0:
+ proc_fd_flags = proc_ofiles[count].f_flags
+ proc_fd_fglob = proc_ofiles[count].f_fglob
+ proc_fd_ftype = unsigned(proc_fd_fglob.fg_ops.fo_type)
+ if proc_fd_ftype == filetype_KQUEUE:
+ q = Cast(proc_fd_fglob.fg_data, 'struct kqueue *')
+ queues.append(q)
+ count += 1
+
+ return queues
+
+def GetAllKqueues():
+ for t in kern.tasks:
+ if unsigned(t.bsd_info) == 0:
+ continue
+ pval = Cast(t.bsd_info, 'proc *')
+ for kq in GetProcKqueues(pval):
+ yield kq
+
+#Macro: showallkqueues
+@lldb_command('showallkqueues' ,'')
+def ShowAllKqueues(cmd_args=[], cmd_options={}):
+ """ Display a summary of all the kqueues in the system """
+ for kq in GetAllKqueues():
+ print GetKQueueSummary.header
+ print GetKQueueSummary(kq)
+ print "\n\n"
+#EndMacro: showallkqueues
+
+#Macro: showkqueue
+@lldb_command('showkqueue' ,'')
+def ShowKQueue(cmd_args=[], cmd_options={}):
+ """ Given a struct kqueue pointer, display the summary of the kqueue
+ Usage: (lldb) showkqueue <struct kqueue *>
+ """
+ if not cmd_args:
+ raise ArgumentError('Invalid arguments')
+
+ kq = kern.GetValueFromAddress(cmd_args[0], 'struct kqueue *')
+ print GetKQueueSummary.header
+ print GetKQueueSummary(kq)
+
+#EndMacro: showkqueue
+
#Macro: showtty
@lldb_command('showtty')
#EndMacro: showtty
+#Macro showallttydevs
+
+@lldb_command('showallttydevs')
+def ShowAllTTYDevs(cmd_args=[], cmd_options={}):
+ """ Show a list of ttydevs registered in the system.
+ Usage:
+ (lldb)showallttydevs
+ """
+ tty_dev_head = kern.globals.tty_dev_head
+ tty_dev = tty_dev_head
+ print GetTTYDevSummary.header
+ while unsigned(tty_dev) != 0:
+ print GetTTYDevSummary(tty_dev)
+ tty_dev = tty_dev.next
+ return ""
+
+#EndMacro: showallttydevs
+
+#Macro: dumpthread_terminate_queue
+
+@lldb_command('dumpthread_terminate_queue')
+def DumpThreadTerminateQueue(cmd_args=None):
+ """ Displays the contents of the specified call_entry queue.
+ Usage: dumpthread_terminate_queue
+ """
+
+ count = 0
+ print GetThreadSummary.header
+ for th in IterateQueue(addressof(kern.globals.thread_terminate_queue), 'struct thread *', 'q_link'):
+ print GetThreadSummary(th)
+ count += 1
+ print "{0: <d} entries!".format(count)
+
+#EndMacro: dumpthread_terminate_queue
+
+#Macro: dumpcrashed_thread_queue
+
+@lldb_command('dumpcrashed_thread_queue')
+def DumpCrashedThreadsQueue(cmd_args=None):
+ """ Displays the contents of the specified call_entry queue.
+ Usage: dumpcrashed_thread_queue
+ """
+
+ count = 0
+ print GetThreadSummary.header
+ for th in IterateQueue(addressof(kern.globals.crashed_threads_queue), 'struct thread *', 'q_link'):
+ print GetThreadSummary(th)
+ count += 1
+ print "{0: <d} entries!".format(count)
+
+#EndMacro: dumpcrashed_thread_queue
+
#Macro: dumpcallqueue
@lldb_command('dumpcallqueue')
Usage: dumpcallqueue <queue_head_t *>
"""
if not cmd_args:
- print DumpCallQueue.__doc__
- return
+ raise ArgumentError("Invalid arguments")
+
print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC')
callhead = kern.GetValueFromAddress(cmd_args[0], 'queue_head_t *')
count = 0
#EndMacro: dumpcallqueue
-@lldb_command('showalltasks')
-def ShowAllTasks(cmd_args=None):
+@lldb_command('showalltasklogicalwrites')
+def ShowAllTaskIOStats(cmd_args=None):
+ """ Commad to print I/O stats for all tasks
+ """
+ print "{0: <20s} {1: <20s} {2: <20s} {3: <20s} {4: <20s} {5: <20s}".format("task", "Immediate Writes", "Deferred Writes", "Invalidated Writes", "Metadata Writes", "name")
+ for t in kern.tasks:
+ pval = Cast(t.bsd_info, 'proc *')
+ print "{0: <#18x} {1: >20d} {2: >20d} {3: >20d} {4: >20d} {5: <20s}".format(t,
+ t.task_immediate_writes,
+ t.task_deferred_writes,
+ t.task_invalidated_writes,
+ t.task_metadata_writes,
+ str(pval.p_comm))
+
+
+@lldb_command('showalltasks','C')
+def ShowAllTasks(cmd_args=None, cmd_options={}):
""" Routine to print a summary listing of all the tasks
wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
NORM - normal I/O explicitly requested (this is the default)
PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
+ Usage: (lldb) showalltasks -C : describe the corpse structure
"""
global kern
- print GetTaskSummary.header + " " + GetProcSummary.header
+ extra_hdr = ''
+ showcorpse = False
+ if '-C' in cmd_options:
+ showcorpse = True
+ extra_hdr += " " + GetKCDataSummary.header
+
+ print GetTaskSummary.header + extra_hdr + " " + GetProcSummary.header
for t in kern.tasks:
pval = Cast(t.bsd_info, 'proc *')
- print GetTaskSummary(t) +" "+ GetProcSummary(pval)
+ out_str = GetTaskSummary(t, showcorpse) + " " + GetProcSummary(pval)
+ print out_str
+ ZombTasks()
@lldb_command('showterminatedtasks')
def ShowTerminatedTasks(cmd_args=None):
for t in kern.tasks:
ShowTaskThreads([str(int(t))])
print " \n"
+
+ for t in kern.terminated_tasks:
+ print "Terminated: \n"
+ ShowTaskThreads([str(int(t))])
+ print " \n"
+
return
@lldb_command('showtaskthreads', "F:")
if not LazyTarget.GetProcess().SetSelectedThread(lldbthread):
print "Failed to switch thread."
return
+
+@lldb_command('switchtoregs')
+def SwitchToRegs(cmd_args=None):
+ """ Routine to switch to a register state.
+ Usage: (lldb) switchtoregs <struct arm_saved_state[64] *>
+ This command creates a fake thread in lldb with the saved register state.
+ Note: This command ONLY works for ARM based kernel setup.
+ """
+
+ if cmd_args == None or len(cmd_args) < 1:
+ raise ArgumentError("No arguments passed")
+
+ lldb_process = LazyTarget.GetProcess()
+
+ saved_state = ArgumentStringToInt(cmd_args[0])
+ # any change to this logic requires change in operating_system.py as well
+ fake_thread_id = 0xdead0000 | (saved_state & ~0xffff0000)
+ fake_thread_id = fake_thread_id & 0xdeadffff
+ lldb_process.CreateOSPluginThread(0xdeadbeef, saved_state)
+ lldbthread = lldb_process.GetThreadByID(int(fake_thread_id))
+
+ if not lldbthread.IsValid():
+ print "Failed to create thread"
+ return
+
+ lldb_process.selected_thread = lldbthread
+ if not lldb_process.SetSelectedThread(lldbthread):
+ print "Failed to switch thread"
+ print "Switched to Fake thread created from register state at 0x%x" % saved_state
+
+
+
# Macro: showallstacks
@lldb_command('showallstacks')
def ShowAllStacks(cmd_args=None):
"""
for t in kern.tasks:
ShowTaskStacks(t)
- print " \n"
+ print " \n"
+ ZombStacks()
return
# EndMacro: showallstacks
processor_list = kern.GetGlobalVariable('processor_list')
current_processor = processor_list
while unsigned(current_processor) > 0:
- print "\nProcessor {: <#020x} State {: <d} (cpu_id {: >#04x})".format(current_processor, int(current_processor.state), int(current_processor.cpu_id))
+ print "\n" + GetProcessorSummary(current_processor)
active_thread = current_processor.active_thread
if unsigned(active_thread) != 0 :
task_val = active_thread.task
processor_list = kern.GetGlobalVariable('processor_list')
current_processor = processor_list
while unsigned(current_processor) > 0:
- print "Processor {: <#020x} State {: <d} (cpu_id {: >#04x})".format(current_processor, int(current_processor.state), int(current_processor.cpu_id))
+ print GetProcessorSummary(current_processor)
active_thread = current_processor.active_thread
if unsigned(active_thread) != 0 :
task_val = active_thread.task
# <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header
mh_execute_addr = int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16)
while frame_ptr and frame_ptr != previous_frame_ptr and bt_count < 128:
- if (kern.arch != 'arm' and frame_ptr < mh_execute_addr) or (kern.arch == 'arm' and frame_ptr > mh_execute_addr):
+ 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):
break
pc_val = kern.GetValueFromAddress(frame_ptr + kern.ptrsize,'uintptr_t *')
pc_val = unsigned(dereference(pc_val))
def FullBackTrace(cmd_args=[]):
""" Show full backtrace across the interrupt boundary.
Syntax: fullbt <frame ptr>
- Example: kfullbt `$rbp`
+ Example: fullbt `$rbp`
"""
if len(cmd_args) < 1:
print FullBackTrace.__doc__
return False
print GetFullBackTrace(ArgumentStringToInt(cmd_args[0]), prefix="\t")
+@lldb_command('fullbtall')
+def FullBackTraceAll(cmd_args=[]):
+ """ Show full backtrace across the interrupt boundary for threads running on all processors.
+ Syntax: fullbtall
+ Example: fullbtall
+ """
+ for processor in IterateLinkedList(kern.globals.processor_list, 'processor_list') :
+ print "\n" + GetProcessorSummary(processor)
+ active_thread = processor.active_thread
+ if unsigned(active_thread) != 0 :
+ task_val = active_thread.task
+ proc_val = Cast(task_val.bsd_info, 'proc *')
+ print GetTaskSummary.header + " " + GetProcSummary.header
+ print GetTaskSummary(task_val) + " " + GetProcSummary(proc_val)
+ print "\t" + GetThreadSummary.header
+ print "\t" + GetThreadSummary(active_thread)
+ print "\tBacktrace:"
+
+ ThreadVal = GetLLDBThreadForKernelThread(active_thread)
+
+ FramePtr = ThreadVal.frames[0].GetFP()
+
+ print GetFullBackTrace(unsigned(FramePtr), prefix="\t")
+
@lldb_command('symbolicate')
def SymbolicateAddress(cmd_args=[]):
params: processor - value representing struct processor *
return: str - representing the details of given processor
"""
- out_str = "Processor {: <#012x} ".format(processor)
- out_str += "State {:d} (cpu_id {:#x})\n".format(processor.state, processor.cpu_id)
+
+ processor_state_str = "INVALID"
+ processor_state = int(processor.state)
+
+ processor_states = {
+ 0: 'OFF_LINE',
+ 1: 'SHUTDOWN',
+ 2: 'START',
+ # 3 (formerly INACTIVE)
+ 4: 'IDLE',
+ 5: 'DISPATCHING',
+ 6: 'RUNNING'
+ }
+
+ if processor_state in processor_states:
+ processor_state_str = "{0: <11s} ".format(processor_states[processor_state])
+
+ processor_recommended_str = ""
+ if int(processor.is_recommended) == 0:
+ processor_recommended_str = " (not recommended)"
+
+ ast = 0
+ preemption_disable = 0
+ preemption_disable_str = ""
+
+ if kern.arch == 'x86_64':
+ cpu_data = kern.globals.cpu_data_ptr[processor.cpu_id]
+ if (cpu_data != 0) :
+ ast = cpu_data.cpu_pending_ast
+ preemption_disable = cpu_data.cpu_preemption_level
+ # On arm64, it's kern.globals.CpuDataEntries[processor.cpu_id].cpu_data_vaddr
+ # but LLDB can't find CpuDataEntries...
+
+ ast_str = GetASTSummary(ast)
+
+ if (preemption_disable != 0) :
+ preemption_disable_str = "Preemption Disabled"
+
+ out_str = "Processor {: <#018x} cpu_id {:>#4x} AST: {:<6s} State {:<s}{:<s} {:<s}\n".format(
+ processor, int(processor.cpu_id), ast_str, processor_state_str, processor_recommended_str,
+ preemption_disable_str)
return out_str
+def GetGroupSetSummary(runq, task_map):
+ """ Internal function to print summary of group run queue
+ params: runq - value representing struct run_queue *
+ return: str - representing the details of given run_queue
+ """
+ out_str = " runq: count {: <10d} highq: {: <10d} urgency {: <10d}\n".format(runq.count, runq.highq, runq.urgency)
+
+ runq_queue_i = 0
+ runq_queue_count = sizeof(runq.queues)/sizeof(runq.queues[0])
+
+ for runq_queue_i in range(runq_queue_count) :
+ runq_queue_head = addressof(runq.queues[runq_queue_i])
+ runq_queue_p = runq_queue_head.next
+
+ if unsigned(runq_queue_p) != unsigned(runq_queue_head):
+ runq_queue_this_count = 0
+
+ for entry in IterateQueue(runq_queue_head, "sched_entry_t", "links"):
+ runq_queue_this_count += 1
+
+ out_str += " Queue [{: <#012x}] Priority {: <3d} count {:d}\n".format(runq_queue_head, runq_queue_i, runq_queue_this_count)
+ for entry in IterateQueue(runq_queue_head, "sched_entry_t", "links"):
+ group_addr = unsigned(entry) - (sizeof(dereference(entry)) * unsigned(entry.sched_pri))
+ group = kern.GetValueFromAddress(unsigned(group_addr), 'sched_group_t')
+ task = task_map.get(unsigned(group), 0x0)
+ if task == 0x0 :
+ print "Cannot find task for group: {: <#012x}".format(group)
+ out_str += "\tEntry [{: <#012x}] Priority {: <3d} Group {: <#012x} Task {: <#012x}\n".format(unsigned(entry), entry.sched_pri, unsigned(group), unsigned(task))
+
+ return out_str
+
+@lldb_command('showrunq')
+def ShowRunq(cmd_args=None):
+ """ Routine to print information of a runq
+ Usage: showrunq <runq>
+ """
+ out_str = ''
+ runq = kern.GetValueFromAddress(cmd_args[0], 'struct run_queue *')
+ out_str += GetRunQSummary(runq)
+ print out_str
+
def GetRunQSummary(runq):
""" Internal function to print summary of run_queue
params: runq - value representing struct run_queue *
return: str - representing the details of given run_queue
"""
- out_str = " Priority Run Queue Info: Count {: <10d}\n".format(runq.count)
+ out_str = " runq: count {: <10d} highq: {: <10d} urgency {: <10d}\n".format(runq.count, runq.highq, runq.urgency)
+
runq_queue_i = 0
runq_queue_count = sizeof(runq.queues)/sizeof(runq.queues[0])
- while runq.count and (runq_queue_i < runq_queue_count):
+
+ for runq_queue_i in range(runq_queue_count) :
runq_queue_head = addressof(runq.queues[runq_queue_i])
runq_queue_p = runq_queue_head.next
+
if unsigned(runq_queue_p) != unsigned(runq_queue_head):
runq_queue_this_count = 0
- while runq_queue_p != runq_queue_head:
- runq_queue_this_count = runq_queue_this_count + 1
- runq_queue_p_thread = Cast(runq_queue_p, 'thread_t')
- # Get the task information
- out_str += GetTaskSummary.header + " " + GetProcSummary.header
- pval = Cast(runq_queue_p_thread.task.bsd_info, 'proc *')
- out_str += GetTaskSummary(runq_queue_p_thread.task) +" "+ GetProcSummary(pval)
- # Get the thread information with related stack traces
- out_str += GetThreadSummary.header + GetThreadSummary(runq_queue_p_thread)
- out_str += GetThreadBackTrace(LazyTarget.GetProcess().GetThreadByID(int(runq_queue_p_thread.thread_id)),
- prefix="\t")
- runq_queue_p = runq_queue_p.next
-
- out_str += " Queue Priority {: <3d} [{: <#012x}] Count {:d}\n".format(runq_queue_i,
- runq_queue_head, runq_queue_this_count)
-
- runq_queue_i = runq_queue_i + 1
+
+ for thread in IterateQueue(runq_queue_head, "thread_t", "links"):
+ runq_queue_this_count += 1
+
+ out_str += " Queue [{: <#012x}] Priority {: <3d} count {:d}\n".format(runq_queue_head, runq_queue_i, runq_queue_this_count)
+ out_str += "\t" + GetThreadSummary.header + "\n"
+ for thread in IterateQueue(runq_queue_head, "thread_t", "links"):
+ out_str += "\t" + GetThreadSummary(thread) + "\n"
+ if config['verbosity'] > vHUMAN :
+ out_str += "\t" + GetThreadBackTrace(thread, prefix="\t\t") + "\n"
return out_str
+
def GetGrrrSummary(grrr_runq):
""" Internal function to print summary of grrr_run_queue
params: grrr_runq - value representing struct grrr_run_queue *
grrr_runq.weight, grrr_runq.current_group)
grrr_group_i = 0
grrr_group_count = sizeof(grrr_runq.groups)/sizeof(grrr_runq.groups[0])
- while grrr_runq.count and (grrr_group_i < grrr_group_count):
+ for grrr_group_i in range(grrr_group_count) :
grrr_group = addressof(grrr_runq.groups[grrr_group_i])
- runq_queue_p = runq_queue_head.next
if grrr_group.count > 0:
out_str += " Group {: <3d} [{: <#012x}] ".format(grrr_group.index, grrr_group)
out_str += "Count {:d} Weight {:d}\n".format(grrr_group.count, grrr_group.weight)
grrr_group_client_head = addressof(grrr_group.clients)
- grrr_group_client = grrr_group_client_head.next
- while grrr_group_client != grrr_group_client_head:
- grrr_group_client_thread = Cast(grrr_group_client, 'thread_t')
- # Get the task information
- out_str += GetTaskSummary.header + " " + GetProcSummary.header
- pval = Cast(grrr_group_client_thread.task.bsd_info, 'proc *')
- out_str += GetTaskSummary(grrr_group_client_thread.task) +" "+ GetProcSummary(pval)
- # Get the thread information with related stack traces
- out_str += GetThreadSummary.header + GetThreadSummary(grrr_group_client_thread)
- out_str += GetThreadBackTrace(LazyTarget.GetProcess().GetThreadByID(int(grrr_group_client_thread.thread_id)),
- prefix="\t")
- grrr_group_client = grrr_group_client.next
- grrr_group_i = grrr_group_i + 1
+ out_str += GetThreadSummary.header
+ for thread in IterateQueue(grrr_group_client_head, "thread_t", "links"):
+ out_str += "\t" + GetThreadSummary(thread) + "\n"
+ if config['verbosity'] > vHUMAN :
+ out_str += "\t" + GetThreadBackTrace(thread, prefix="\t\t") + "\n"
+ return out_str
+
+def ShowNextThread(processor):
+ out_str = ""
+ if (processor.next_thread != 0) :
+ out_str += " " + "Next thread:\n"
+ out_str += "\t" + GetThreadSummary.header + "\n"
+ out_str += "\t" + GetThreadSummary(processor.next_thread) + "\n"
+ return out_str
+
+def ShowActiveThread(processor):
+ out_str = ""
+ if (processor.active_thread != 0) :
+ out_str += "\t" + GetThreadSummary.header + "\n"
+ out_str += "\t" + GetThreadSummary(processor.active_thread) + "\n"
return out_str
@lldb_command('showallprocessors')
show_grrr = 0
show_priority_runq = 0
show_priority_pset_runq = 0
- show_fairshare_grrr = 0
- show_fairshare_list = 0
- sched_enum_val = kern.globals._sched_enum
+ show_group_pset_runq = 0
+ sched_string = str(kern.globals.sched_current_dispatch.sched_name)
- if sched_enum_val == 1:
+ if sched_string == "traditional":
show_priority_runq = 1
- show_fairshare_list = 1
- elif sched_enum_val == 2:
+ elif sched_string == "traditional_with_pset_runqueue":
show_priority_pset_runq = 1
- show_fairshare_list = 1
- elif sched_enum_val == 4:
+ elif sched_string == "grrr":
show_grrr = 1
- show_fairshare_grrr = 1
- elif sched_enum_val == 5:
+ elif sched_string == "multiq":
show_priority_runq = 1
- show_fairshare_list = 1
- elif sched_enum_val == 6:
- show_priority_pset_runq = 1
- show_fairshare_list = 1
+ show_group_pset_runq = 1
+ elif sched_string == "dualq":
+ show_priority_pset_runq = 1
+ show_priority_runq = 1
+ else :
+ print "Unknown sched_string {:s}".format(sched_string)
out_str = ''
- while pset:
+
+ out_str += "Scheduler: {:s} ({:s})\n".format(sched_string,
+ kern.Symbolicate(unsigned(kern.globals.sched_current_dispatch)))
+
+ out_str += "Runnable threads: {:d} Timeshare threads: {:d} Background threads: {:d}\n".format(
+ kern.globals.sched_run_count, kern.globals.sched_share_count, kern.globals.sched_background_count)
+
+ if show_group_pset_runq:
+ # Create a group->task mapping
+ task_map = {}
+ for task in kern.tasks:
+ task_map[unsigned(task.sched_group)] = task
+ for task in kern.terminated_tasks:
+ task_map[unsigned(task.sched_group)] = task
+
+ while unsigned(pset) != 0:
out_str += "Processor Set {: <#012x} Count {:d} (cpu_id {:<#x}-{:<#x})\n".format(pset,
pset.cpu_set_count, pset.cpu_set_low, pset.cpu_set_hi)
+
+ if show_priority_pset_runq:
+ runq = pset.pset_runq
+ out_str += GetRunQSummary(runq)
+
+ if show_group_pset_runq:
+ out_str += "Main Runq:\n"
+ runq = pset.pset_runq
+ out_str += GetGroupSetSummary(runq, task_map)
+ out_str += "All Groups:\n"
+ # TODO: Possibly output task header for each group
+ for group in IterateQueue(kern.globals.sched_groups, "sched_group_t", "sched_groups"):
+ if (group.runq.count != 0) :
+ task = task_map.get(unsigned(group), "Unknown task!")
+ out_str += "Group {: <#012x} Task {: <#012x}\n".format(unsigned(group), unsigned(task))
+ out_str += GetRunQSummary(group.runq)
+
out_str += " Active Processors:\n"
- active_queue_head = addressof(pset.active_queue)
- active_elt = active_queue_head.next
- while active_elt != active_queue_head:
- processor = Cast(active_elt, 'processor *')
+ for processor in IterateQueue(pset.active_queue, "processor_t", "processor_queue"):
out_str += " "
out_str += GetProcessorSummary(processor)
+ out_str += ShowActiveThread(processor)
+ out_str += ShowNextThread(processor)
+
if show_priority_runq:
- runq = addressof(processor.runq)
+ runq = processor.runq
out_str += GetRunQSummary(runq)
if show_grrr:
- grrr_runq = addressof(processor.grrr_runq)
+ grrr_runq = processor.grrr_runq
out_str += GetGrrrSummary(grrr_runq)
-
- if processor.processor_meta and (processor.processor_meta.primary ==
- processor):
- processor_meta_idle_head = addressof(processor.processor_meta.idle_queue)
- processor_meta_idle = processor_meta_idle_head.next
- while processor_meta_idle != processor_meta_idle_head:
- out_str += " Idle Meta Processor: "
- out_str += GetProcessorSummary(processor_meta_idle)
- processor_meta_idle = processor_meta_idle.next
- active_elt = active_elt.next
out_str += " Idle Processors:\n"
- idle_queue_head = addressof(pset.idle_queue)
- idle_elt = idle_queue_head.next
- while idle_elt != idle_queue_head:
- processor = Cast(idle_elt, 'processor *')
- out_str += " "
- out_str += GetProcessorSummary(processor)
-
- if processor.processor_meta and (processor.processor_meta.primary ==
- processor):
- processor_meta_idle_head = addressof(processor.processor_meta.idle_queue)
- processor_meta_idle = processor_meta_idle_head.next
- while processor_meta_idle != processor_meta_idle_head:
- out_str += " Idle Meta Processor: "
- out_str += GetProcessorSummary(processor_meta_idle)
- processor_meta_idle = processor_meta_idle.next
- idle_elt = idle_elt.next
-
- if show_priority_pset_runq:
- runq = addressof(pset.pset_runq)
- out_str += "\n" + GetRunQSummary(runq)
+ for processor in IterateQueue(pset.idle_queue, "processor_t", "processor_queue"):
+ out_str += " " + GetProcessorSummary(processor)
+ out_str += ShowActiveThread(processor)
+ out_str += ShowNextThread(processor)
+
+ if show_priority_runq:
+ out_str += GetRunQSummary(processor.runq)
+
+ out_str += " Idle Secondary Processors:\n"
+ for processor in IterateQueue(pset.idle_secondary_queue, "processor_t", "processor_queue"):
+ out_str += " " + GetProcessorSummary(processor)
+ out_str += ShowActiveThread(processor)
+ out_str += ShowNextThread(processor)
+
+ if show_priority_runq:
+ out_str += GetRunQSummary(processor.runq)
+
pset = pset.pset_list
- out_str += "\nRealtime Queue Count {:d}\n".format(kern.globals.rt_runq.count)
- rt_runq_head = addressof(kern.globals.rt_runq.queue)
- rt_runq_local = rt_runq_head.next
- while rt_runq_local != rt_runq_head:
- rt_runq_thread = Cast(rt_runq_local, 'thread *')
- out_str += ShowTask([unsigned(rt_runq_thread.task)])
- out_str += ShowAct([unsigned(rt_runq_thread)])
- rt_runq_local = rt_runq_local.next
+ out_str += "\nRealtime Queue ({:<#012x}) Count {:d}\n".format(addressof(kern.globals.rt_runq.queue), kern.globals.rt_runq.count)
+ if kern.globals.rt_runq.count != 0:
+ out_str += "\t" + GetThreadSummary.header + "\n"
+ for rt_runq_thread in IterateQueue(kern.globals.rt_runq.queue, "thread_t", "links"):
+ out_str += "\t" + GetThreadSummary(rt_runq_thread) + "\n"
+
+ out_str += "\nTerminate Queue: ({:<#012x})\n".format(addressof(kern.globals.thread_terminate_queue))
+ first = False
+ for thread in IterateQueue(kern.globals.thread_terminate_queue, "thread_t", "links"):
+ if first:
+ out_str += "\t" + GetThreadSummary.header + "\n"
+ first = True
+ out_str += "\t" + GetThreadSummary(thread) + "\n"
+
+ out_str += "\nCrashed Threads Queue: ({:<#012x})\n".format(addressof(kern.globals.crashed_threads_queue))
+ first = False
+ for thread in IterateQueue(kern.globals.crashed_threads_queue, "thread_t", "links"):
+ if first:
+ out_str += "\t" + GetThreadSummary.header + "\n"
+ first = True
+ out_str += "\t" + GetThreadSummary(thread) + "\n"
+
+ out_str += "\n"
out_str += "\n"
- if show_fairshare_list:
- out_str += "Fair Share Queue Count {:d}\n".format(kern.globals.fs_runq.count)
- fs_runq_head = addressof(kern.globals.fs_runq.queue)
- fs_runq_local = fs_runq_head.next
- while fs_runq_local != fs_runq_head:
- fs_runq_thread = Cast(fs_runq, 'thread *')
- out_str += ShowTask([unsigned(fs_runq_thread.task)])
- out_str += ShowAct([unsigned(rt_runq_thread)])
- fs_runq_local = fs_runq_local.next
- if show_fairshare_grrr:
- out_str += "Fair Share Queue Count {:d}\n".format(kern.globals.fs_grrr_runq.count)
- fs_grrr = addressof(kern.globals.fs_grrr_runq)
- out_str += GetGrrrSummary(fs_grrr)
print out_str
# EndMacro: showallprocessors
lf_tracking_max = 0x4000
out_str = ''
- now = kern.globals.sched_tick / 20
+ now = unsigned(kern.globals.sched_tick) / 20
lim_pct = 0
- out_str += "{: >25s} {:<d}:".format(ledger_template.lt_entries[i].et_key, i)
- out_str += "{: >13d} ".format(ledger.le_credit - ledger.le_debit)
+ out_str += "{: >32s} {:<2d}:".format(ledger_template.lt_entries[i].et_key, i)
+ out_str += "{: >15d} ".format(unsigned(ledger.le_credit) - unsigned(ledger.le_debit))
if (ledger.le_flags & lf_tracking_max):
- out_str += "{:9d} {:5d} ".format(ledger._le.le_peaks[0].le_max, now - ledger._le.le_peaks[0].le_time)
- out_str += "{:9d} {:4d} ".format(ledger._le.le_peaks[1].le_max, now - ledger._le.le_peaks[1].le_time)
+ out_str += "{:9d} {:5d} ".format(ledger._le.le_peaks[0].le_max, now - unsigned(ledger._le.le_peaks[0].le_time))
+ out_str += "{:9d} {:4d} ".format(ledger._le.le_peaks[1].le_max, now - unsigned(ledger._le.le_peaks[1].le_time))
else:
out_str += " - - - - "
- out_str += "{:12d} {:12d} ".format(ledger.le_credit, ledger.le_debit)
+ out_str += "{:12d} {:12d} ".format(unsigned(ledger.le_credit), unsigned(ledger.le_debit))
if (unsigned(ledger.le_limit) != ledger_limit_infinity):
out_str += "{:12d} ".format(unsigned(ledger.le_limit))
else:
else:
out_str += " - "
- if ((ledger.le_credit - ledger.le_debit) > unsigned(ledger.le_limit)):
+ if ((unsigned(ledger.le_credit) - unsigned(ledger.le_debit)) > unsigned(ledger.le_limit)):
out_str += " X "
else:
out_str += " "
i = i + 1
return out_str
-@header("{0: <15s} {1: >9s} {2: <2s} {3: >12s} {4: >9s} {5: >6s} {6: >8s} {7: <10s} {8: <9s} \
+@header("{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >9s} {5: >6s} {6: >8s} {7: <10s} {8: <9s} \
{9: <12s} {10: <7s} {11: <15s} {12: <8s} {13: <9s} {14: <6s} {15: >6s}".format(
"task [thread]", "entry", "#", "balance", "peakA", "(age)", "peakB", "(age)", "credit",
"debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags"))
["t_int_gpu_deny", "gpudeny-int"],
["t_ext_gpu_deny", "gpudeny-ext"],
["t_role", "role"],
- ["t_visibility", "vis"],
["t_tal_enabled", "tal-enabled"],
["t_base_latency_qos", "latency-base"],
["t_over_latency_qos", "latency-override"],
["t_sup_timer", "timer-throttling"],
["t_sup_disk", "disk-throttling"],
["t_sup_cpu_limit", "cpu-limits"],
- ["t_sup_suspend", "suspend"]
+ ["t_sup_suspend", "suspend"],
+ ["t_sup_bg_sockets", "bg-sockets"]
]
suppression=""
["t_latency_qos", "latency-qos"],
["t_through_qos", "throughput-qos"],
["t_sup_active", "suppression-active"],
- ["t_role", "role"],
- ["t_visibility", "vis"]
+ ["t_role", "role"]
]
effective=""
print "pended: " + pended
+@lldb_type_summary(['wait_queue', 'wait_queue_t'])
+@header("{: <20s} {: <20s} {: <15s} {:<5s} {:<5s} {: <20s}".format("waitq", "interlock", "policy", "members", "threads", "eventmask"))
+def GetWaitQSummary(waitq):
+ """ Summarizes the important fields in task structure.
+ params: task: value - value object representing a task in kernel
+ returns: str - summary of the task
+ """
+ out_string = ""
+ format_string = '{: <#020x} {: <#020x} {: <15s} {: <5d} {: <5d} {: <#020x}'
+
+ wqtype = ""
+
+ if (waitq.wq_fifo == 1) :
+ wqtype += "FIFO"
+ else :
+ wqtype += "PRIO"
+
+ if (waitq.wq_prepost == 1) :
+ wqtype += "Prepost"
+
+ if (waitq.wq_type == 0x3) :
+ wqtype += "Set"
+ elif (waitq.wq_type == 0x2) :
+ wqtype += "Queue"
+ else :
+ wqtype += "INVALID"
+
+ out_string += format_string.format(waitq, unsigned(waitq.wq_interlock.lock_data), policy, 0, 0, unsigned(waitq.wq_eventmask))
+
+ out_string += "\n" + GetThreadSummary.header
+
+ for thread in IterateQueue(waitq.wq_queue, "thread_t", "links"):
+ out_string += "\n" + GetThreadSummary(thread)
+
+ return out_string
+
+
+@lldb_command('showallsuspendedtasks', '')
+def ShowSuspendedTasks(cmd_args=[], options={}):
+ """ Show a list of suspended tasks with their process name summary.
+ """
+ print GetTaskSummary.header + ' ' + GetProcSummary.header
+ for t in kern.tasks:
+ if t.suspend_count > 0:
+ print GetTaskSummary(t) + ' ' + GetProcSummary(Cast(t.bsd_info, 'proc *'))
+ return True