import time
import xnudefines
import memory
+import json
+
+def GetProcName(proc):
+ """ returns a string name of the process. Longer variant is preffered if provided.
+ params:
+ proc: value object representing a proc in the kernel.
+ returns:
+ str: a string name of the process linked to the task.
+ """
+ name = str(proc.p_name)
+ if name != '':
+ return name
+ else:
+ return str(proc.p_comm)
def GetProcNameForTask(task):
""" returns a string name of the process. if proc is not valid "unknown" is returned
if not task or not unsigned(task.bsd_info):
return "unknown"
p = Cast(task.bsd_info, 'proc *')
- return str(p.p_comm)
+
+ return GetProcName(p)
def GetProcPIDForTask(task):
""" returns a int pid of the process. if the proc is not valid, val[5] from audit_token is returned.
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])
str : A string describing various information for process.
"""
out_string = ""
- out_string += ("Process {p: <#020x}\n\tname {p.p_comm: <20s}\n\tpid:{p.p_pid: <6d} " +
+ out_string += ("Process {p: <#020x}\n\tname {0: <32s}\n\tpid:{p.p_pid: <6d} " +
"task:{p.task: <#020x} p_stat:{p.p_stat: <6d} parent pid: {p.p_ppid: <6d}\n"
- ).format(p=proc)
+ ).format(GetProcName(proc), p=proc)
#print the Creds
ucred = proc.p_ucred
if ucred:
"""
for p in kern.procs:
if int(p.p_pid) == int(pid):
- return str(p.p_comm)
+ return GetProcName(p)
return "Unknown"
def GetProcForPid(search_pid):
# EndMacro: showtaskcoalitions
@lldb_type_summary(['proc', 'proc *'])
-@header("{0: >6s} {1: <18s} {2: >11s} {3: ^10s} {4: <20s}".format("pid", "process", "io_policy", "wq_state", "command"))
+@header("{0: >6s} {1: <18s} {2: >11s} {3: ^10s} {4: <32s}".format("pid", "process", "io_policy", "wq_state", "command"))
def GetProcSummary(proc):
""" Summarize the process data.
params:
str - string summary of the process.
"""
out_string = ""
- format_string= "{0: >6d} {1: <#018x} {2: >11s} {3: >2d} {4: >2d} {5: >2d} {6: <20s}"
+ format_string= "{0: >6d} {1: <#018x} {2: >11s} {3: >2d} {4: >2d} {5: >2d} {6: <32s}"
pval = proc.GetSBValue()
#code.interact(local=locals())
if str(pval.GetType()) != str(gettype('proc *')) :
wq_num_threads = -1
wq_idle_threads = -1
wq_req_threads = -1
- process_name = str(proc.p_comm)
+ process_name = GetProcName(proc)
if process_name == 'xpcproxy':
for thread in IterateQueue(task.threads, 'thread *', 'task_threads'):
thread_name = GetThreadName(thread)
while count <= proc_lastfile:
if unsigned(proc_ofiles[count]) != 0:
out_str = ''
- proc_fd_flags = proc_ofiles[count].f_flags
- proc_fd_fglob = proc_ofiles[count].f_fglob
+ proc_fd_flags = proc_ofiles[count].fp_flags
+ proc_fd_fglob = proc_ofiles[count].fp_glob
out_str += "{0: <5d} ".format(count)
out_str += "{0: <#18x} ".format(unsigned(proc_fd_fglob))
out_str += "0x{0:0>8x} ".format(unsigned(proc_fd_flags))
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} {6: <20s} {7: <20s} {8: <20s} {9: <20s}".format("task", "Immediate Writes", "Deferred Writes", "Invalidated Writes", "Metadata Writes", "Immediate Writes to External", "Deferred Writes to External", "Invalidated Writes to External", "Metadata Writes to External", "name")
+ print "{0: <20s} {1: <20s} {2: <20s} {3: <20s} {4: <20s} {5: <20s} {6: <20s} {7: <20s} {8: <20s} {9: <32}".format("task", "Immediate Writes", "Deferred Writes", "Invalidated Writes", "Metadata Writes", "Immediate Writes to External", "Deferred Writes to External", "Invalidated Writes to External", "Metadata Writes to External", "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} {6: <20s} {7: <20s} {8: <20s} {9: <20s}".format(t,
t.task_writes_counters_external.task_deferred_writes,
t.task_writes_counters_external.task_invalidated_writes,
t.task_writes_counters_external.task_metadata_writes,
- str(pval.p_comm))
+ GetProcName(pval))
@lldb_command('showalltasks','C', fancy=True)
print GetTaskSummary.header + " " + GetProcSummary.header
for tasklist in [kern.tasks, kern.terminated_tasks]:
for t in tasklist:
- if t.map.pmap == pmap:
+ if kern.GetValueFromAddress(unsigned(t.map.pmap), 'pmap_t') == pmap:
pval = Cast(t.bsd_info, 'proc *')
out_str = GetTaskSummary(t) + " " + GetProcSummary(pval)
print out_str
retval = []
for t in kern.tasks:
pval = Cast(t.bsd_info, "proc *")
- process_name = "{:s}".format(pval.p_comm)
+ process_name = "{:s}".format(GetProcName(pval))
if search_regex.search(process_name):
retval.append(t)
return retval
out_string = hdr_format.format("PID", "PROCESS", "POINTER")
out_string += hdr_format.format('='*3, '='*7, '='*7)
proc = GetProcForPid(search_pid)
- out_string += "{0: <6d} {1: <14s} [ {2: #019x} ]\n".format(proc.p_ppid, proc.p_pptr.p_comm, unsigned(proc.p_pptr))
- out_string += "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(proc.p_pid, proc.p_comm, unsigned(proc))
+ out_string += "{0: <6d} {1: <32s} [ {2: #019x} ]\n".format(proc.p_ppid, GetProcName(proc.p_pptr), unsigned(proc.p_pptr))
+ out_string += "|--{0: <6d} {1: <32s} [ {2: #019x} ]\n".format(proc.p_pid, GetProcName(proc), unsigned(proc))
print out_string
ShowProcTreeRecurse(proc, "| ")
head_ptr = proc.p_children.lh_first
for p in IterateListEntry(proc.p_children, 'struct proc *', 'p_sibling'):
- print prefix + "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(p.p_pid, p.p_comm, unsigned(p))
+ print prefix + "|--{0: <6d} {1: <32s} [ {2: #019x} ]\n".format(p.p_pid, GetProcName(p), unsigned(p))
ShowProcTreeRecurse(p, prefix + "| ")
@lldb_command('showthreadfortid')
preemption_disable_str)
return out_str
-def GetLedgerEntrySummary(ledger_template, ledger, i, show_footprint_interval_max=False):
+def GetLedgerEntry(ledger_template, ledger, i):
""" Internal function to get internals of a ledger entry (*not* a ledger itself)
params: ledger_template - value representing struct ledger_template_t for the task or thread
ledger - value representing struct ledger_entry *
- return: str - formatted output information of ledger entries
+ return: entry - entry dictionary
"""
ledger_limit_infinity = (uint64_t(0x1).value << 63) - 1
lf_refill_scheduled = 0x0400
lf_tracking_max = 0x4000
- out_str = ''
now = unsigned(kern.globals.sched_tick) / 20
lim_pct = 0
- 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))
+ entry = {}
+
+ entry["key"] = str(ledger_template.lt_entries[i].et_key)
+ entry["credit"] = unsigned(ledger.le_credit)
+ entry["debit"] = unsigned(ledger.le_debit)
+ entry["balance"] = entry["credit"] - entry["debit"]
if (ledger.le_flags & lf_tracking_max):
- if (show_footprint_interval_max):
- out_str += "{:12d} ".format(ledger._le._le_max.le_interval_max)
- out_str += "{:14d} ".format(ledger._le._le_max.le_lifetime_max)
- else:
- if (show_footprint_interval_max):
+ entry["interval_max"] = unsigned(ledger._le._le_max.le_interval_max)
+ entry["lifetime_max"] = unsigned(ledger._le._le_max.le_lifetime_max)
+
+ if (unsigned(ledger.le_limit) != ledger_limit_infinity):
+ entry["limit"] = unsigned(ledger.le_limit)
+
+ if (ledger.le_flags & lf_refill_scheduled):
+ entry["refill_period"] = unsigned (ledger._le.le_refill.le_refill_period)
+
+ if (unsigned(ledger.le_warn_percent) < 65535):
+ entry["warn_percent"] = unsigned (ledger.le_warn_percent * 100 / 65536)
+ entry["flags"] = int(ledger.le_flags)
+
+ return entry
+
+def FormatLedgerEntrySummary(entry, i, show_footprint_interval_max=False):
+ """ internal function to format a ledger entry into a string
+ params: entry - A python dictionary containing the ledger entry
+ return: str - formatted output information of ledger entries
+ """
+ out_str = ''
+ out_str += "{: >32s} {:<2d}:".format(entry["key"], i)
+ out_str += "{: >15d} ".format(entry["balance"])
+
+ if (show_footprint_interval_max):
+ if entry.has_key("interval_max"):
+ out_str += "{:12d} ".format(entry["interval_max"])
+ else:
out_str += " - "
+
+ if entry.has_key("lifetime_max"):
+ out_str += "{:14d} ".format(entry["lifetime_max"])
+ else:
out_str += " - "
- 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))
+
+ out_str += "{:12d} {:12d} ".format(entry["credit"], entry["debit"])
+ if entry.has_key("limit"):
+ out_str += "{:12d} ".format(unsigned(entry["limit"]))
else:
out_str += " - "
- if (ledger.le_flags & lf_refill_scheduled):
- out_str += "{:15d} ".format(ledger._le.le_refill.le_refill_period)
+ if entry.has_key("refill_period"):
+ out_str += "{:15d} ".format(entry["refill_period"])
+ out_str += "{:9d} ".format((entry["limit"] * 100) / entry["refill_period"])
else:
out_str += " - "
-
- if (ledger.le_flags & lf_refill_scheduled):
- out_str += "{:9d} ".format((unsigned(ledger.le_limit) * 100) / ledger._le.le_refill.le_refill_period)
- else:
out_str += " - "
- if (unsigned(ledger.le_warn_level) != ledger_limit_infinity):
- out_str += "{:9d} ".format((unsigned(ledger.le_warn_level) * 100) / unsigned(ledger.le_limit))
+ if entry.has_key("warn_percent"):
+ out_str += "{:9d} ".format(entry["warn_percent"])
else:
out_str += " - "
- if ((unsigned(ledger.le_credit) - unsigned(ledger.le_debit)) > unsigned(ledger.le_limit)):
- out_str += " X "
+ if entry.has_key("limit"):
+ if entry["balance"] > entry["limit"]:
+ out_str += " X "
+ else:
+ out_str += " "
else:
out_str += " "
- out_str += "{:#8x}\n".format(ledger.le_flags)
+ out_str += "{:#8x}\n".format(entry["flags"])
return out_str
-def GetThreadLedgerSummary(thread_val):
+def GetLedgerEntrySummary(ledger_template, ledger, i, show_footprint_interval_max=False):
+ """ internal function to get internals of a ledger entry (*not* a ledger itself)
+ params: ledger_template - value representing struct ledger_template_t for the task or thread
+ ledger - value representing struct ledger_entry *
+ return: str - formatted output information of ledger entries
+ """
+ entry = GetLedgerEntry(ledger_template, ledger, i)
+ return FormatLedgerEntrySummary(entry, i)
+
+
+def GetThreadLedgers(thread_val):
""" Internal function to get a summary of ledger entries for the given thread
- params: thread - value representing struct thread *
- return: str - formatted output information for ledger entries of the input thread
+ params: thread_val - value representing struct thread *
+ return: thread - python dictionary containing threads's ledger entries. This can
+ be printed directly with FormatThreadLedgerSummmary or outputted as json.
"""
- out_str = " [{:#08x}]\n".format(thread_val)
+ thread = {}
+ thread["address"] = unsigned(thread_val)
ledgerp = thread_val.t_threadledger
+ thread["entries"] = []
if ledgerp:
i = 0
while i != ledgerp.l_template.lt_cnt:
- out_str += GetLedgerEntrySummary(kern.globals.thread_ledger_template,
- ledgerp.l_entries[i], i)
+ thread["entries"].append(GetLedgerEntry(kern.globals.thread_ledger_template,
+ ledgerp.l_entries[i], i))
i = i + 1
+ return thread
+
+def FormatThreadLedgerSummary(thread):
+ """ Internal function to print a thread's ledger entries
+ params: thread - python dictionary containing thread's ledger entries
+ return: str - formatted output information for ledger entries of the input thread
+ """
+ out_str = " [{:#08x}]\n".format(thread["address"])
+ entries = thread["entries"]
+ for i, entry in enumerate(entries):
+ out_str += FormatLedgerEntrySummary(entry, i)
return out_str
-def GetTaskLedgers(task_val, show_footprint_interval_max=False):
+def GetTaskLedgers(task_val):
""" Internal function to get summary of ledger entries from the task and its threads
params: task_val - value representing struct task *
- return: str - formatted output information for ledger entries of the input task
+ return: task - python dictionary containing tasks's ledger entries. This can
+ be printed directly with FormatTaskLedgerSummary or outputted as json.
"""
- out_str = ''
task_ledgerp = task_val.ledger
i = 0
- out_str += "{: #08x} ".format(task_val)
+ tasks = []
+ task = {}
+ task["address"] = unsigned(task_val)
+
pval = Cast(task_val.bsd_info, 'proc *')
if pval:
- out_str += "{: <5s}:\n".format(pval.p_comm)
- else:
- out_str += "Invalid process:\n"
+ task["name"] = GetProcName(pval)
+ task["pid"] = int(pval.p_pid)
+
+ task["entries"] = []
while i != task_ledgerp.l_template.lt_cnt:
- out_str += GetLedgerEntrySummary(kern.globals.task_ledger_template, task_ledgerp.l_entries[i], i, show_footprint_interval_max)
+ task["entries"].append(GetLedgerEntry(kern.globals.task_ledger_template, task_ledgerp.l_entries[i], i))
i = i + 1
# Now walk threads
+ task["threads"] = []
for thval in IterateQueue(task_val.threads, 'thread *', 'task_threads'):
- out_str += GetThreadLedgerSummary(thval)
+ task["threads"].append(GetThreadLedgers(thval))
+
+ return task
+@header("{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >14s} {5: >12s} {6: >12s} {7: >12s} {8: <15s} {9: <8s} {10: <9s} {11: <6s} {12: >6s}".format(
+ "task [thread]", "entry", "#", "balance", "lifetime_max", "credit",
+ "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags"))
+def FormatTaskLedgerSummary(task, show_footprint_interval_max=False):
+ """ Internal function to get summary of ledger entries from the task and its threads
+ params: task_val - value representing struct task *
+ return: str - formatted output information for ledger entries of the input task
+ """
+ out_str = ''
+ out_str += "{: #08x} ".format(task["address"])
+ if task.has_key("name"):
+ out_str += "{: <5s}:\n".format(task["name"])
+ else:
+ out_str += "Invalid process\n"
+
+ for i, entry in enumerate(task["entries"]):
+ out_str += FormatLedgerEntrySummary(entry, i, show_footprint_interval_max)
+
+ for thread in task["threads"]:
+ out_str += FormatThreadLedgerSummary(thread)
return out_str
+
# Macro: showtaskledgers
-@lldb_command('showtaskledgers', 'F:I')
+@lldb_command('showtaskledgers', 'JF:I')
def ShowTaskLedgers(cmd_args=None, cmd_options={}):
""" Routine to print a summary of ledger entries for the task and all of its threads
- or : showtaskledgers [ -I ] [ -F ] <task>
+ or : showtaskledgers [ -I ] [-J] [ -F ] <task>
options:
-I: show footprint interval max (DEV/DEBUG only)
-F: specify task via name instead of address
+ -J: output json
-
"""
+ print_json = False
if "-F" in cmd_options:
task_list = FindTasksByName(cmd_options["-F"])
for tval in task_list:
- print GetTaskLedgers.header
- print GetTaskLedgers(tval)
+ print FormatTaskLedgerSummary.header
+ ledgers = GetTaskLedgers(tval)
+ print FormatTaskLedgerSummary(ledgers)
return
+ if "-J" in cmd_options:
+ print_json = True
if not cmd_args:
raise ArgumentError("No arguments passed.")
tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
if not tval:
raise ArgumentError("unknown arguments: %r" %cmd_args)
- if (show_footprint_interval_max):
- print "{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >12s} {5: >14s} {6: >12s} {7: >12s} {8: >12s} {9: <15s} {10: <8s} {11: <9s} {12: <6s} {13: >6s}".format(
- "task [thread]", "entry", "#", "balance", "intrvl_max", "lifetime_max", "credit",
- "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags")
+ ledgers = GetTaskLedgers(tval)
+ if print_json:
+ print json.dumps(ledgers)
else:
- print "{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >14s} {5: >12s} {6: >12s} {7: >12s} {8: <15s} {9: <8s} {10: <9s} {11: <6s} {12: >6s}".format(
- "task [thread]", "entry", "#", "balance", "lifetime_max", "credit",
- "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags")
- print GetTaskLedgers(tval, show_footprint_interval_max)
+ if (show_footprint_interval_max):
+ print "{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >12s} {5: >14s} {6: >12s} {7: >12s} {8: >12s} {9: <15s} {10: <8s} {11: <9s} {12: <6s} {13: >6s}".format(
+ "task [thread]", "entry", "#", "balance", "intrvl_max", "lifetime_max", "credit",
+ "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags")
+ else:
+ print FormatTaskLedgerSummary.header
+ print FormatTaskLedgerSummary(ledgers, show_footprint_interval_max)
# EndMacro: showtaskledgers
# Macro: showalltaskledgers
-@lldb_command('showalltaskledgers')
+@lldb_command('showalltaskledgers', "J")
def ShowAllTaskLedgers(cmd_args=None, cmd_options={}):
""" Routine to print a summary of ledger entries for all tasks and respective threads
- Usage: showalltaskledgers
+ Usage: showalltaskledgers [-J]
+ -J : Output json
"""
+ print_json = False
+ if "-J" in cmd_options:
+ print_json = True
+ tasks = []
for t in kern.tasks:
task_val = unsigned(t)
- ShowTaskLedgers([task_val], cmd_options=cmd_options)
+ if not print_json:
+ ShowTaskLedgers([task_val], cmd_options=cmd_options)
+ else:
+ tasks.append(GetTaskLedgers(t))
+ if print_json:
+ print json.dumps(tasks)
# EndMacro: showalltaskledgers
procp = Cast(taskp.bsd_info, 'proc *')
out_str = "task = {:#x} pte = {:#x}\t".format(taskp, taskp.map.pmap.ttep)
if procp != 0:
- out_str += "{:s}\n".format(procp.p_comm)
+ out_str += "{:s}\n".format(GetProcName(procp))
else:
out_str += "\n"
print out_str
if unsigned(proc_ofiles[count]) != 0:
proc_file_count += 1
count += 1
- print "{0: <#020x} {1: <20s} {2: >10d}".format(proc, proc.p_comm, proc_file_count)
+ print "{0: <#020x} {1: <32s} {2: >10d}".format(proc, GetProcName(proc), proc_file_count)
#EndMacro: showprocfilessummary
if(thval==threadval):
pval = Cast(t.bsd_info, 'proc *')
- process_name = "{:s}".format(pval.p_comm)
+ process_name = "{:s}".format(GetProcName(pval))
print "\n\n"
print " *** Continuing to dump the thread stacks from the process *** :" + " " + process_name
print "\n\n"