1from core.cvalue import sizeof, value 2from enum import Enum 3from memory import GetLedgerEntryWithName, Memstats 4from process import GetProcName, GetProcPID, GetTaskFromProc, GetTaskSummary, ledger_limit_infinity 5from scheduler import GetRecentTimestamp 6from utils import Cast 7from xnu import header, kern, lldb_command, unsigned 8from xnudefines import JETSAM_PRIORITY_MAX, P_MEMSTAT_FROZEN 9 10 11# Macro: showmemorystatus 12 13class PControlAction(Enum): 14 # See proc_internal.h 15 NONE = 0 16 THROTTLE = 1 17 SUSPEND = 2 18 KILL = 3 19 20class RelaunchProbability(Enum): 21 # See kern_memorystatus.h 22 LOW = 1 23 MED = 2 24 HIGH = 4 25 26def CalculateLedgerPeak(phys_footprint_entry): 27 """ 28 Internal function to calculate ledger peak value for the given phys footprint entry 29 params: phys_footprint_entry - value representing struct ledger_entry * 30 return: value - representing the ledger peak for the given phys footprint entry 31 """ 32 return max(phys_footprint_entry['balance'], phys_footprint_entry.get('interval_max', 0)) 33 34@header(f'{"cur_pri": <12s} ' 35 f'{"name": <32s} ' 36 f'{"pid": >8s} ' 37 f'{"req_pri": >12s} ' 38 f'{"ast_pri": >12s} ' 39 f'{"state": >12s} ' 40 f'{"dirty": >12s} ' 41 f'{"relaunch": >10s} ' 42 f'{"pcontrol": >10s} ' 43 f'{"paction": >10s} ' 44 f'{"footprint": >12s} ' 45 f'{"max_footprint": >13s} ' 46 f'{"limit": >12s}') 47def GetMemoryStatusNode(proc): 48 """ 49 Internal function to get memorystatus information from the given proc 50 params: proc - value representing struct proc * 51 return: str - formatted output information for proc object 52 """ 53 54 task_val = GetTaskFromProc(proc) 55 if task_val is None: 56 return '' 57 58 task_ledgerp = task_val.ledger 59 ledger_template = kern.globals.task_ledger_template 60 61 task_physmem_footprint_ledger_entry = GetLedgerEntryWithName(ledger_template, task_ledgerp, 'phys_mem') 62 task_iokit_footprint_ledger_entry = GetLedgerEntryWithName(ledger_template, task_ledgerp, 'iokit_mapped') 63 task_phys_footprint_ledger_entry = GetLedgerEntryWithName(ledger_template, task_ledgerp, 'phys_footprint') 64 page_size = kern.globals.page_size 65 66 phys_mem_footprint = task_physmem_footprint_ledger_entry['balance'] // 1024 67 iokit_footprint = task_iokit_footprint_ledger_entry['balance'] // 1024 68 phys_footprint = task_phys_footprint_ledger_entry['balance'] // 1024 69 if task_phys_footprint_ledger_entry['limit'] == ledger_limit_infinity: 70 phys_footprint_limit = '-' 71 else: 72 phys_footprint_limit = str(task_phys_footprint_ledger_entry['limit'] // 1024) 73 ledger_peak = CalculateLedgerPeak(task_phys_footprint_ledger_entry) // 1024 74 phys_footprint_spike = ledger_peak // 1024 75 phys_footprint_lifetime_max = task_phys_footprint_ledger_entry['lifetime_max'] // 1024 76 77 if proc.p_memstat_relaunch_flags != 0: 78 relaunch_flags = RelaunchProbability(int(proc.p_memstat_relaunch_flags)).name 79 else: 80 relaunch_flags = '-' 81 82 if proc.p_pcaction != 0: 83 pc_control = PControlAction(proc.p_pcaction & 0xff).name 84 pc_action = PControlAction((proc.p_pcaction & 0xff00) >> 16).name 85 else: 86 pc_control = '-' 87 pc_action = '-' 88 89 return (f'{proc.p_memstat_effectivepriority:<12d} ' 90 f'{GetProcName(proc):<32s} ' 91 f'{GetProcPID(proc):>8d} ' 92 f'{proc.p_memstat_requestedpriority:>12d} ' 93 f'{proc.p_memstat_assertionpriority:>12d} ' 94 f'{proc.p_memstat_state:#12x} ' 95 f'{proc.p_memstat_dirty:#12x} ' 96 f'{relaunch_flags:>10s} ' 97 f'{pc_control:>10s} ' 98 f'{pc_action:>10s} ' 99 f'{phys_footprint:>12d} ' 100 f'{phys_footprint_lifetime_max:>13d} ' 101 f'{phys_footprint_limit:>12s}') 102 103@lldb_command('showmemorystatus') 104def ShowMemoryStatus(cmd_args=None): 105 """ 106 Routine to display each entry in jetsam list with a summary of pressure statistics 107 Usage: showmemorystatus 108 """ 109 bucket_index = 0 110 print(GetMemoryStatusNode.header) 111 while bucket_index <= JETSAM_PRIORITY_MAX: 112 current_bucket = kern.globals.memstat_bucket[bucket_index] 113 current_list = current_bucket.list 114 current_proc = Cast(current_list.tqh_first, 'proc *') 115 while unsigned(current_proc) != 0: 116 print(GetMemoryStatusNode(current_proc)) 117 current_proc = current_proc.p_memstat_list.tqe_next 118 bucket_index += 1 119 120# EndMacro: showmemorystatus 121