1 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. 4""" 5from __future__ import absolute_import, division, print_function 6 7from builtins import hex 8from builtins import range 9 10from xnu import * 11import sys, shlex 12from utils import * 13from core.lazytarget import * 14import time 15import xnudefines 16import kmemory 17import memory 18import json 19from collections import defaultdict, namedtuple 20 21NO_PROC_NAME = "unknown" 22P_LHASTASK = 0x00000002 23TF_HAS_PROC = 0x00800000 24 25def GetProcPID(proc): 26 """ returns the PID of a process. 27 params: 28 proc: value object representing a proc in the kernel. 29 returns: 30 int: the pid of the process. 31 """ 32 return unsigned(proc.p_pid) if proc else -1 33 34def GetProcPlatform(proc): 35 """ returns the platform identifier of a process. 36 params: 37 proc: value object representing a proc in the kernel. 38 returns: 39 int: the platform identifier of the process. 40 """ 41 if not proc: 42 return None 43 return int(proc.p_proc_ro.p_platform_data.p_platform) 44 45def GetProcName(proc): 46 """ returns a string name of the process. Longer variant is preffered if provided. 47 params: 48 proc: value object representing a proc in the kernel. 49 returns: 50 str: a string name of the process linked to the task. 51 """ 52 if not proc: 53 return NO_PROC_NAME 54 name = str(proc.p_name) 55 return name if name != '' else str(proc.p_comm) 56 57def GetProcNameForTask(task): 58 """ returns a string name of the process. If proc is not valid the proc 59 name is looked up in the associated importance structure (if 60 available). If no name can be found, "unknown" is returned. 61 params: 62 task: value object represeting a task in the kernel. 63 returns: 64 str : A string name of the process linked to the task 65 """ 66 if task: 67 p = GetProcFromTask(task) 68 if p: 69 return GetProcName(p) 70 71 if (hasattr(task, 'task_imp_base') and 72 hasattr(task.task_imp_base, 'iit_procname') and 73 unsigned(task.task_imp_base) != 0): 74 return str(task.task_imp_base.iit_procname) 75 76 return NO_PROC_NAME 77 78def GetProcPIDForTask(task): 79 """ returns a int pid of the process. if the proc is not valid, val[5] from audit_token is returned. 80 params: 81 task: value object representing a task in the kernel 82 returns: 83 int : pid of the process or -1 if not found 84 """ 85 if not task: 86 return -1 87 88 p = GetProcFromTask(task) 89 if p: 90 return GetProcPID(p) 91 92 proc_ro = Cast(task.bsd_info_ro, 'proc_ro *') 93 pid = unsigned(proc_ro.task_tokens.audit_token.val[5]) 94 return pid 95 96def GetProcStartAbsTimeForTask(task): 97 if task: 98 p = GetProcFromTask(task) 99 if unsigned(p): 100 return p.p_stats.ps_start 101 return None 102 103def GetProcInfo(proc): 104 """ returns a string name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields. 105 params: 106 proc : value object representing a proc in the kernel 107 returns: 108 str : A string describing various information for process. 109 """ 110 out_string = "" 111 out_string += ("Process {p: <#020x}\n\tname {0: <32s}\n\tpid:{1: <6d} " + 112 "task:{task: <#020x} p_stat:{p.p_stat: <6d} parent pid: {p.p_ppid: <6d}\n" 113 ).format(GetProcName(proc), GetProcPID(proc), task=GetTaskFromProc(proc), p=proc) 114 #print the Creds 115 ucred = proc.p_proc_ro.p_ucred.__smr_ptr 116 if ucred: 117 out_string += "Cred: euid {:d} ruid {:d} svuid {:d}\n".format(ucred.cr_posix.cr_uid, 118 ucred.cr_posix.cr_ruid, 119 ucred.cr_posix.cr_svuid ) 120 #print the flags 121 flags = int(proc.p_flag) 122 out_string += "Flags: {0: <#020x}\n".format(flags) 123 num = 1 124 while num <= flags: 125 if flags & num: 126 explain_str = xnudefines.proc_flag_explain_strings.get(num, 'unknown') 127 out_string += "\t0x{:08x} - ".format(num) + explain_str + "\n" 128 elif num == 0x4: #special case for 32bit flag 129 out_string += "\t!0x00000004 - process is 32 bit\n" 130 num = num << 1 131 out_string += "State: " 132 state_val = proc.p_stat 133 if state_val < 1 or state_val > len(xnudefines.proc_state_strings) : 134 out_string += "(Unknown)" 135 else: 136 out_string += xnudefines.proc_state_strings[int(state_val)] 137 138 return out_string 139 140def GetProcNameForPid(pid): 141 """ Finds the name of the process corresponding to a given pid 142 params: 143 pid : int, pid you want to find the procname for 144 returns 145 str : Name of the process corresponding to the pid, "Unknown" if not found 146 """ 147 for p in kern.procs: 148 if int(GetProcPID(p)) == int(pid): 149 return GetProcName(p) 150 return NO_PROC_NAME 151 152def GetProcForPid(search_pid): 153 """ Finds the value object representing a proc in the kernel based on its pid 154 params: 155 search_pid : int, pid whose proc structure you want to find 156 returns: 157 value : The value object representing the proc, if a proc corresponding 158 to the given pid is found. Returns None otherwise 159 """ 160 if search_pid == 0: 161 return kern.globals.initproc 162 else: 163 headp = kern.globals.allproc 164 for proc in IterateListEntry(headp, 'p_list'): 165 if GetProcPID(proc) == search_pid: 166 return proc 167 return None 168 169@lldb_command('allproc') 170def AllProc(cmd_args=None): 171 """ Walk through the allproc structure and print procinfo for each process structure. 172 params: 173 cmd_args - [] : array of strings passed from lldb command prompt 174 """ 175 for proc in kern.procs : 176 print(GetProcInfo(proc)) 177 178 179@lldb_command('zombproc') 180def ZombProc(cmd_args=None): 181 """ Routine to print out all procs in the zombie list 182 params: 183 cmd_args - [] : array of strings passed from lldb command prompt 184 """ 185 if any(kern.zombprocs): 186 print("\nZombie Processes:") 187 for proc in kern.zombprocs: 188 print(GetProcInfo(proc) + "\n\n") 189 190@lldb_command('zombtasks') 191def ZombTasks(cmd_args=None): 192 """ Routine to print out all tasks in the zombie list 193 params: None 194 """ 195 out_str = "" 196 if any(kern.zombprocs): 197 header = "\nZombie Tasks:\n" 198 header += GetTaskSummary.header + " " + GetProcSummary.header 199 for proc in kern.zombprocs: 200 if proc.p_stat != 5: 201 t = GetTaskFromProc(proc) 202 out_str += GetTaskSummary(t) +" "+ GetProcSummary(proc) + "\n" 203 if out_str != "": 204 print(header) 205 print(out_str) 206 207@lldb_command('zombstacks', fancy=True) 208def ZombStacks(cmd_args=None, cmd_options={}, O=None): 209 """ Routine to print out all stacks of tasks that are exiting 210 """ 211 header_flag = 0 212 for proc in kern.zombprocs: 213 if proc.p_stat != 5: 214 if header_flag == 0: 215 print("\nZombie Stacks:") 216 header_flag = 1 217 t = GetTaskFromProc(proc) 218 ShowTaskStacks(t, O=O) 219#End of Zombstacks 220 221def GetASTSummary(ast): 222 """ Summarizes an AST field 223 Flags: 224 P - AST_PREEMPT 225 Q - AST_QUANTUM 226 U - AST_URGENT 227 H - AST_HANDOFF 228 Y - AST_YIELD 229 A - AST_APC 230 L - AST_LEDGER 231 B - AST_BSD 232 K - AST_KPERF 233 M - AST_MACF 234 r - AST_RESET_PCS 235 a - AST_ARCADE 236 G - AST_GUARD 237 T - AST_TELEMETRY_USER 238 T - AST_TELEMETRY_KERNEL 239 T - AST_TELEMETRY_WINDOWED 240 S - AST_SFI 241 D - AST_DTRACE 242 I - AST_TELEMETRY_IO 243 E - AST_KEVENT 244 R - AST_REBALANCE 245 p - AST_PROC_RESOURCE 246 """ 247 out_string = "" 248 state = int(ast) 249 thread_state_chars = {0x0:'', 0x1:'P', 0x2:'Q', 0x4:'U', 0x8:'H', 0x10:'Y', 0x20:'A', 250 0x40:'L', 0x80:'B', 0x100:'K', 0x200:'M', 0x400: 'r', 0x800: 'a', 251 0x1000:'G', 0x2000:'T', 0x4000:'T', 0x8000:'T', 0x10000:'S', 252 0x20000: 'D', 0x40000: 'I', 0x80000: 'E', 0x100000: 'R', 0x400000: 'p'} 253 state_str = '' 254 mask = 0x1 255 while mask <= 0x200000: 256 state_str += thread_state_chars[int(state & mask)] 257 mask = mask << 1 258 259 return state_str 260 261 262@lldb_type_summary(['kcdata_descriptor *', 'kcdata_descriptor_t']) 263@header("{0: <20s} {1: <20s} {2: <20s} {3: <10s} {4: <5s}".format("kcdata_descriptor", "begin_addr", "cur_pos", "size", "flags")) 264def GetKCDataSummary(kcdata): 265 """ Summarizes kcdata_descriptor structure 266 params: kcdata: value - value object representing kcdata_descriptor 267 returns: str - summary of the kcdata object 268 """ 269 format_string = "{0: <#020x} {1: <#020x} {2: <#020x} {3: <10d} {4: <#05x}" 270 return format_string.format(kcdata, kcdata.kcd_addr_begin, kcdata.kcd_addr_end, kcdata.kcd_length, kcdata.kcd_flags) 271 272 273@lldb_type_summary(['task', 'task_t']) 274@header("{0: <20s} {1: <20s} {2: <20s} {3: >5s} {4: <5s}".format("task","vm_map", "ipc_space", "#acts", "flags")) 275def GetTaskSummary(task, showcorpse=False): 276 """ Summarizes the important fields in task structure. 277 params: task: value - value object representing a task in kernel 278 returns: str - summary of the task 279 """ 280 out_string = "" 281 format_string = '{0: <#020x} {1: <#020x} {2: <#020x} {3: >5d} {4: <5s}' 282 thread_count = int(task.thread_count) 283 task_flags = '' 284 if hasattr(task, "suppression_generation") and (int(task.suppression_generation) & 0x1) == 0x1: 285 task_flags += 'P' 286 if hasattr(task, "effective_policy") and int(task.effective_policy.tep_sup_active) == 1: 287 task_flags += 'N' 288 if hasattr(task, "suspend_count") and int(task.suspend_count) > 0: 289 task_flags += 'S' 290 if hasattr(task, 'task_imp_base') and unsigned(task.task_imp_base): 291 tib = task.task_imp_base 292 if int(tib.iit_receiver) == 1: 293 task_flags += 'R' 294 if int(tib.iit_donor) == 1: 295 task_flags += 'D' 296 if int(tib.iit_assertcnt) > 0: 297 task_flags += 'B' 298 299 proc_ro = Cast(task.bsd_info_ro, 'proc_ro *') 300 301 # check if corpse flag is set 302 if unsigned(proc_ro.t_flags_ro) & 0x20: 303 task_flags += 'C' 304 if unsigned(task.t_flags) & 0x40: 305 task_flags += 'P' 306 307 out_string += format_string.format(task, task.map, task.itk_space, thread_count, task_flags) 308 if showcorpse is True and unsigned(task.corpse_info) != 0: 309 out_string += " " + GetKCDataSummary(task.corpse_info) 310 return out_string 311 312def GetMachThread(uthread): 313 """ Converts the passed in value interpreted as a uthread_t into a thread_t 314 """ 315 addr = unsigned(uthread) - sizeof('struct thread') 316 thread = kern.GetValueFromAddress(addr, 'struct thread *') 317 return thread 318 319def GetBSDThread(thread): 320 """ Converts the passed in value interpreted as a thread_t into a uthread_t 321 """ 322 addr = unsigned(thread) + sizeof('struct thread') 323 return kern.GetValueFromAddress(addr, 'struct uthread *') 324 325def GetProcFromTask(task): 326 """ Converts the passed in value interpreted as a task_t into a proc_t 327 """ 328 if unsigned(task) and unsigned(task.t_flags) & TF_HAS_PROC: 329 addr = unsigned(task) - kern.globals.proc_struct_size 330 return value(task.GetSBValue().xCreateValueFromAddress( 331 'proc', addr, gettype('struct proc') 332 ).AddressOf()) 333 return kern.GetValueFromAddress(0, 'proc *') 334 335def GetTaskFromProc(proc): 336 """ Converts the passed in value interpreted as a proc_t into a task_t 337 """ 338 if unsigned(proc) and unsigned(proc.p_lflag) & P_LHASTASK: 339 addr = unsigned(proc) + kern.globals.proc_struct_size 340 return value(proc.GetSBValue().xCreateValueFromAddress( 341 'task', addr, gettype('struct task') 342 ).AddressOf()) 343 return kern.GetValueFromAddress(0, 'task *') 344 345def GetThreadName(thread): 346 """ Get the name of a thread, if possible. Returns the empty string 347 otherwise. 348 """ 349 uthread = GetBSDThread(thread) 350 if int(uthread.pth_name) != 0 : 351 th_name_strval = Cast(uthread.pth_name, 'char *') 352 if len(str(th_name_strval)) > 0 : 353 return str(th_name_strval) 354 355 return '' 356 357ThreadSummary = namedtuple('ThreadSummary', [ 358 'thread', 'tid', 'task', 'processor', 'base', 'pri', 'sched_mode', 'io_policy', 359 'state', 'ast', 'waitq', 'wait_evt', 'wait_evt_sym', 'wait_msg', 360 'name']) 361ThreadSummaryNames = ThreadSummary(*ThreadSummary._fields) 362ThreadSummaryFormat = ( 363 '{ts.thread: <20s} {ts.tid: <10s} {ts.task: <20s} {ts.processor: <20s} {ts.base: <6s} ' 364 '{ts.pri: <6s} {ts.sched_mode: <10s} {ts.io_policy: <15s} ' 365 '{ts.state: <8s} {ts.ast: <12s} {ts.waitq: <18s} {ts.wait_evt: <18s} ' 366 '{ts.wait_evt_sym: <30s} {ts.wait_msg: <20s} {ts.name: <20s}') 367 368@lldb_type_summary(['thread *', 'thread_t']) 369@header(ThreadSummaryFormat.format(ts=ThreadSummaryNames)) 370def GetThreadSummary(thread, O=None): 371 """ Summarize the thread structure. 372 373 params: thread: value - value object representing a thread in kernel 374 returns: str - summary of a thread 375 376 State flags: 377 W - Wait asserted 378 S - Suspended 379 R - Runnable 380 U - Uninterruptible 381 H - Terminated 382 A - Terminated (on queue) 383 I - Idle thread 384 C - Crashed thread 385 K - Waking 386 387 policy flags: 388 B - darwinbg 389 T - IO throttle 390 P - IO passive 391 D - Terminated 392 """ 393 thread_ptr_str = '{:<#018x}'.format(thread) 394 thread_task_ptr_str = '{:<#018x}'.format(thread.t_tro.tro_task) 395 396 if int(thread.static_param): 397 thread_ptr_str += ' W' 398 thread_id = hex(thread.thread_id) 399 processor = hex(thread.last_processor) 400 base_priority = str(int(thread.base_pri)) 401 sched_priority = str(int(thread.sched_pri)) 402 sched_mode = '' 403 mode = str(thread.sched_mode) 404 if 'TIMESHARE' in mode: 405 sched_mode += 'TMSHR' 406 elif 'FIXED' in mode: 407 sched_mode += 'FIXED' 408 elif 'REALTIME' in mode: 409 sched_mode += 'RT' 410 411 if (unsigned(thread.bound_processor) != 0): 412 sched_mode += ' BIND' 413 414 TH_SFLAG_THROTTLED = 0x4 415 if (unsigned(thread.sched_flags) & TH_SFLAG_THROTTLED): 416 sched_mode += ' BG' 417 418 thread_name = GetThreadName(thread) 419 uthread = GetBSDThread(thread) 420 421 io_policy_str = "" 422 if int(uthread.uu_flag) & 0x400: 423 io_policy_str += 'RAGE ' 424 if int(thread.effective_policy.thep_darwinbg) != 0: 425 io_policy_str += 'B' 426 if int(thread.effective_policy.thep_io_tier) != 0: 427 io_policy_str += 'T' 428 if int(thread.effective_policy.thep_io_passive) != 0: 429 io_policy_str += 'P' 430 if int(thread.effective_policy.thep_terminated) != 0: 431 io_policy_str += 'D' 432 433 state = int(thread.state) 434 thread_state_chars = { 435 0x0: '', 0x1: 'W', 0x2: 'S', 0x4: 'R', 0x8: 'U', 0x10: 'H', 0x20: 'A', 436 0x40: 'P', 0x80: 'I', 0x100: 'K' 437 } 438 state_str = '' 439 mask = 0x1 440 while mask <= 0x100: 441 state_str += thread_state_chars[int(state & mask)] 442 mask <<= 1 443 444 if int(thread.inspection): 445 state_str += 'C' 446 447 ast = int(thread.ast) | int(thread.reason) 448 ast_str = GetASTSummary(ast) 449 450 wait_queue_str = '' 451 wait_event_str = '' 452 wait_event_str_sym = '' 453 wait_message = '' 454 if (state & 0x1) != 0: 455 wait_queue_str = '{:<#018x}'.format(unsigned(thread.waitq.wq_q)) 456 wait_event_str = '{:<#018x}'.format(unsigned(thread.wait_event)) 457 wait_event_str_sym = kern.Symbolicate(int(hex(thread.wait_event), 16)) 458 uthread = GetBSDThread(thread) 459 if int(uthread.uu_wmesg) != 0: 460 wait_message = str(Cast(uthread.uu_wmesg, 'char *')) 461 462 ts = ThreadSummary( 463 thread=thread_ptr_str, tid=thread_id, 464 task=thread_task_ptr_str, processor=processor, 465 base=base_priority, pri=sched_priority, sched_mode=sched_mode, 466 io_policy=io_policy_str, state=state_str, ast=ast_str, 467 waitq=wait_queue_str, wait_evt=wait_event_str, 468 wait_evt_sym=wait_event_str_sym, wait_msg=wait_message, 469 name=thread_name) 470 if O is not None: 471 return O.format(ThreadSummaryFormat, ts=ts) 472 else: 473 return ThreadSummaryFormat.format(ts=ts) 474 475 476def GetTaskRoleString(role): 477 role_strs = { 478 0 : "TASK_UNSPECIFIED", 479 1 : "TASK_FOREGROUND_APPLICATION", 480 2 : "TASK_BACKGROUND_APPLICATION", 481 3 : "TASK_CONTROL_APPLICATION", 482 4 : "TASK_GRAPHICS_SERVER", 483 5 : "TASK_THROTTLE_APPLICATION", 484 6 : "TASK_NONUI_APPLICATION", 485 7 : "TASK_DEFAULT_APPLICATION", 486 } 487 return role_strs[int(role)] 488 489def GetCoalitionFlagString(coal): 490 flags = [] 491 if (coal.privileged): 492 flags.append('privileged') 493 if (coal.termrequested): 494 flags.append('termrequested') 495 if (coal.terminated): 496 flags.append('terminated') 497 if (coal.reaped): 498 flags.append('reaped') 499 if (coal.notified): 500 flags.append('notified') 501 if (coal.efficient): 502 flags.append('efficient') 503 return "|".join(flags) 504 505def GetCoalitionTasks(queue, coal_type, thread_details=False): 506 sfi_strs = { 507 0x0 : "SFI_CLASS_UNSPECIFIED", 508 0x1 : "SFI_CLASS_DARWIN_BG", 509 0x2 : "SFI_CLASS_APP_NAP", 510 0x3 : "SFI_CLASS_MANAGED_FOCAL", 511 0x4 : "SFI_CLASS_MANAGED_NONFOCAL", 512 0x5 : "SFI_CLASS_DEFAULT_FOCAL", 513 0x6 : "SFI_CLASS_DEFAULT_NONFOCAL", 514 0x7 : "SFI_CLASS_KERNEL", 515 0x8 : "SFI_CLASS_OPTED_OUT", 516 0x9 : "SFI_CLASS_UTILITY", 517 0xA : "SFI_CLASS_LEGACY_FOCAL", 518 0xB : "SFI_CLASS_LEGACY_NONFOCAL", 519 0xC : "SFI_CLASS_USER_INITIATED_FOCAL", 520 0xD : "SFI_CLASS_USER_INITIATED_NONFOCAL", 521 0xE : "SFI_CLASS_USER_INTERACTIVE_FOCAL", 522 0xF : "SFI_CLASS_USER_INTERACTIVE_NONFOCAL", 523 0x10 : "SFI_CLASS_MAINTENANCE", 524 } 525 tasks = [] 526 field_path = '.task_coalition[{}]'.format(coal_type) 527 for task in IterateLinkageChain(queue, 'task *', field_path): 528 task_str = "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(task),task,GetProcNameForTask(task),GetTaskRoleString(task.effective_policy.tep_role)) 529 if thread_details: 530 for thread in IterateQueue(task.threads, "thread_t", "task_threads"): 531 task_str += "\n\t\t\t|-> thread:" + hex(thread) + ", " + sfi_strs[int(thread.sfi_class)] 532 tasks.append(task_str) 533 return tasks 534 535def GetCoalitionTypeString(type): 536 """ Convert a coalition type field into a string 537 Currently supported types (from <mach/coalition.h>): 538 COALITION_TYPE_RESOURCE 539 COALITION_TYPE_JETSAM 540 """ 541 if type == 0: # COALITION_TYPE_RESOURCE 542 return 'RESOURCE' 543 if type == 1: 544 return 'JETSAM' 545 return '<unknown>' 546 547def GetResourceCoalitionSummary(coal, verbose=False): 548 """ Summarize a resource coalition 549 """ 550 out_string = "Resource Coalition:\n\t Ledger:\n" 551 thread_details = False 552 if config['verbosity'] > vSCRIPT: 553 thread_details = True 554 ledgerp = coal.r.ledger 555 if verbose and unsigned(ledgerp) != 0: 556 i = 0 557 while i != ledgerp.l_template.lt_cnt: 558 out_string += "\t\t" 559 out_string += GetLedgerEntrySummary(kern.globals.task_ledger_template, ledgerp, i) 560 i = i + 1 561 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) 562 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) 563 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) 564 if verbose: 565 out_string += "\n\t cpu_time_effective[THREAD_QOS_DEFAULT] {0: <d}".format(coal.r.cpu_time_eqos[0]) 566 out_string += "\n\t cpu_time_effective[THREAD_QOS_MAINTENANCE] {0: <d}".format(coal.r.cpu_time_eqos[1]) 567 out_string += "\n\t cpu_time_effective[THREAD_QOS_BACKGROUND] {0: <d}".format(coal.r.cpu_time_eqos[2]) 568 out_string += "\n\t cpu_time_effective[THREAD_QOS_UTILITY] {0: <d}".format(coal.r.cpu_time_eqos[3]) 569 out_string += "\n\t cpu_time_effective[THREAD_QOS_LEGACY] {0: <d}".format(coal.r.cpu_time_eqos[4]) 570 out_string += "\n\t cpu_time_effective[THREAD_QOS_USER_INITIATED] {0: <d}".format(coal.r.cpu_time_eqos[5]) 571 out_string += "\n\t cpu_time_effective[THREAD_QOS_USER_INTERACTIVE] {0: <d}".format(coal.r.cpu_time_eqos[6]) 572 out_string += "\n\t Tasks:\n\t\t" 573 tasks = GetCoalitionTasks(addressof(coal.r.tasks), 0, thread_details) 574 out_string += "\n\t\t".join(tasks) 575 return out_string 576 577def GetJetsamCoalitionSummary(coal, verbose=False): 578 out_string = "Jetsam Coalition:" 579 thread_details = False 580 if config['verbosity'] > vSCRIPT: 581 thread_details = True 582 if unsigned(coal.j.leader) == 0: 583 out_string += "\n\t NO Leader!" 584 else: 585 out_string += "\n\t Leader:\n\t\t" 586 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)) 587 out_string += "\n\t Extensions:\n\t\t" 588 tasks = GetCoalitionTasks(addressof(coal.j.extensions), 1, thread_details) 589 out_string += "\n\t\t".join(tasks) 590 out_string += "\n\t XPC Services:\n\t\t" 591 tasks = GetCoalitionTasks(addressof(coal.j.services), 1, thread_details) 592 out_string += "\n\t\t".join(tasks) 593 out_string += "\n\t Other Tasks:\n\t\t" 594 tasks = GetCoalitionTasks(addressof(coal.j.other), 1, thread_details) 595 out_string += "\n\t\t".join(tasks) 596 out_string += "\n\t Thread Group: {0: <#020x}\n".format(coal.j.thread_group) 597 return out_string 598 599@lldb_type_summary(['coalition_t', 'coalition *']) 600@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")) 601def GetCoalitionSummary(coal): 602 if unsigned(coal) == 0: 603 return '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'.format(0, "", -1, -1, -1, -1, -1, "") 604 out_string = "" 605 format_string = '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}' 606 type_string = GetCoalitionTypeString(coal.type) 607 flag_string = GetCoalitionFlagString(coal) 608 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) 609 return out_string 610 611def GetCoalitionInfo(coal, verbose=False): 612 """ returns a string describing a coalition, including details about the particular coalition type. 613 params: 614 coal : value object representing a coalition in the kernel 615 returns: 616 str : A string describing the coalition. 617 """ 618 if unsigned(coal) == 0: 619 return "<null coalition>" 620 typestr = GetCoalitionTypeString(coal.type) 621 flagstr = GetCoalitionFlagString(coal) 622 out_string = "" 623 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) 624 if coal.type == 0: # COALITION_TYPE_RESOURCE 625 out_string += GetResourceCoalitionSummary(coal, verbose) 626 elif coal.type == 1: # COALITION_TYPE_JETSAM 627 out_string += GetJetsamCoalitionSummary(coal, verbose) 628 else: 629 out_string += "Unknown Type" 630 631 return out_string 632 633# Macro: showcoalitioninfo 634 635@lldb_command('showcoalitioninfo') 636def ShowCoalitionInfo(cmd_args=None, cmd_options={}): 637 """ Display more detailed information about a coalition 638 Usage: showcoalitioninfo <address of coalition> 639 """ 640 verbose = False 641 if config['verbosity'] > vHUMAN: 642 verbose = True 643 if not cmd_args: 644 raise ArgumentError("No arguments passed") 645 coal = kern.GetValueFromAddress(cmd_args[0], 'coalition *') 646 if not coal: 647 print("unknown arguments:", str(cmd_args)) 648 return False 649 print(GetCoalitionInfo(coal, verbose)) 650 651# EndMacro: showcoalitioninfo 652 653# Macro: showallcoalitions 654 655@lldb_command('showallcoalitions') 656def ShowAllCoalitions(cmd_args=None): 657 """ Print a summary listing of all the coalitions 658 """ 659 global kern 660 print(GetCoalitionSummary.header) 661 for c in kern.coalitions: 662 print(GetCoalitionSummary(c)) 663 664# EndMacro: showallcoalitions 665 666# Macro: showallthreadgroups 667 668@lldb_type_summary(['struct thread_group *', 'thread_group *']) 669@header("{0: <20s} {1: <5s} {2: <16s} {3: <5s} {4: <8s} {5: <20s}".format("thread_group", "id", "name", "refc", "flags", "recommendation")) 670def GetThreadGroupSummary(tg): 671 if unsigned(tg) == 0: 672 return '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}'.format(0, -1, "", -1, "", -1) 673 out_string = "" 674 format_string = '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}' 675 tg_flags = '' 676 if (tg.tg_flags & 0x1): 677 tg_flags += 'E' 678 if (tg.tg_flags & 0x2): 679 tg_flags += 'A' 680 if (tg.tg_flags & 0x4): 681 tg_flags += 'C' 682 if (tg.tg_flags & 0x100): 683 tg_flags += 'U' 684 out_string += format_string.format(tg, tg.tg_id, tg.tg_name, tg.tg_refcount.ref_count, tg_flags, tg.tg_recommendation) 685 return out_string 686 687@lldb_command('showallthreadgroups') 688def ShowAllThreadGroups(cmd_args=None): 689 """ Print a summary listing of all thread groups 690 """ 691 global kern 692 print(GetThreadGroupSummary.header) 693 for tg in kern.thread_groups: 694 print(GetThreadGroupSummary(tg)) 695 696# EndMacro: showallthreadgroups 697 698# Macro: showtaskcoalitions 699 700@lldb_command('showtaskcoalitions', 'F:') 701def ShowTaskCoalitions(cmd_args=None, cmd_options={}): 702 """ 703 """ 704 task_list = [] 705 if "-F" in cmd_options: 706 task_list = FindTasksByName(cmd_options["-F"]) 707 elif cmd_args: 708 t = kern.GetValueFromAddress(cmd_args[0], 'task *') 709 task_list.append(t) 710 else: 711 raise ArgumentError("No arguments passed") 712 713 if len(task_list) > 0: 714 print(GetCoalitionSummary.header) 715 for task in task_list: 716 print(GetCoalitionSummary(task.coalition[0])) 717 print(GetCoalitionSummary(task.coalition[1])) 718 719# EndMacro: showtaskcoalitions 720 721@lldb_type_summary(['proc', 'proc *']) 722@header("{0: >6s} {1: <18s} {2: >11s} {3: ^10s} {4: <32s}".format("pid", "process", "io_policy", "wq_state", "command")) 723def GetProcSummary(proc): 724 """ Summarize the process data. 725 params: 726 proc : value - value representaitng a proc * in kernel 727 returns: 728 str - string summary of the process. 729 """ 730 if not proc: 731 return "Process is not valid." 732 733 out_string = "" 734 format_string= "{0: >6d} {1: <#018x} {2: >11s} {3: >2d} {4: >2d} {5: >2d} {6: <32s}" 735 pval = proc.GetSBValue() 736 #code.interact(local=locals()) 737 if str(pval.GetType()) != str(gettype('proc *')) : 738 return "Unknown type " + str(pval.GetType()) + " " + str(hex(proc)) 739 pid = int(GetProcPID(proc)) 740 proc_addr = int(hex(proc), 16) 741 proc_rage_str = "" 742 if int(proc.p_lflag) & 0x400000 : 743 proc_rage_str = "RAGE" 744 745 task = GetTaskFromProc(proc) 746 747 io_policy_str = "" 748 749 if int(task.effective_policy.tep_darwinbg) != 0: 750 io_policy_str += "B" 751 if int(task.effective_policy.tep_lowpri_cpu) != 0: 752 io_policy_str += "L" 753 754 if int(task.effective_policy.tep_io_tier) != 0: 755 io_policy_str += "T" 756 if int(task.effective_policy.tep_io_passive) != 0: 757 io_policy_str += "P" 758 if int(task.effective_policy.tep_terminated) != 0: 759 io_policy_str += "D" 760 761 if int(task.effective_policy.tep_latency_qos) != 0: 762 io_policy_str += "Q" 763 if int(task.effective_policy.tep_sup_active) != 0: 764 io_policy_str += "A" 765 766 if int(proc.p_refcount) & GetEnumValue("proc_ref_bits_t::P_REF_SHADOW") : 767 io_policy_str += "S" 768 769 770 try: 771 work_queue = proc.p_wqptr 772 if proc.p_wqptr != 0 : 773 wq_num_threads = int(work_queue.wq_nthreads) 774 wq_idle_threads = int(work_queue.wq_thidlecount) 775 wq_req_threads = int(work_queue.wq_reqcount) 776 else: 777 wq_num_threads = 0 778 wq_idle_threads = 0 779 wq_req_threads = 0 780 except: 781 wq_num_threads = -1 782 wq_idle_threads = -1 783 wq_req_threads = -1 784 process_name = GetProcName(proc) 785 if process_name == 'xpcproxy': 786 for thread in IterateQueue(task.threads, 'thread *', 'task_threads'): 787 thread_name = GetThreadName(thread) 788 if thread_name: 789 process_name += ' (' + thread_name + ')' 790 break 791 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) 792 return out_string 793 794@lldb_type_summary(['tty_dev_t', 'tty_dev_t *']) 795@header("{0: <20s} {1: <10s} {2: <10s} {3: <15s} {4: <15s} {5: <15s} {6: <15s}".format("tty_dev","primary", "replica", "open", "free", "name", "revoke")) 796def GetTTYDevSummary(tty_dev): 797 """ Summarizes the important fields in tty_dev_t structure. 798 params: tty_dev: value - value object representing a tty_dev_t in kernel 799 returns: str - summary of the tty_dev 800 """ 801 out_string = "" 802 format_string = "{0: <#020x} {1: <#010x} {2: <#010x} {3: <15s} {4: <15s} {5: <15s} {6: <15s}" 803 open_fn = kern.Symbolicate(int(hex(tty_dev.open), 16)) 804 free_fn = kern.Symbolicate(int(hex(tty_dev.free), 16)) 805 name_fn = kern.Symbolicate(int(hex(tty_dev.name), 16)) 806 revoke_fn = kern.Symbolicate(int(hex(tty_dev.revoke), 16)) 807 out_string += format_string.format(tty_dev, tty_dev.primary, tty_dev.replica, open_fn, free_fn, name_fn, revoke_fn) 808 return out_string 809 810# Macro: showtask 811 812@lldb_command('showtask', 'F:') 813def ShowTask(cmd_args=None, cmd_options={}): 814 """ Routine to print a summary listing of given task 815 Usage: showtask <address of task> 816 or : showtask -F <name of task> 817 """ 818 task_list = [] 819 if "-F" in cmd_options: 820 task_list = FindTasksByName(cmd_options['-F']) 821 else: 822 if not cmd_args: 823 raise ArgumentError("Invalid arguments passed.") 824 825 tval = kern.GetValueFromAddress(cmd_args[0], 'task *') 826 if not tval: 827 raise ArgumentError("Unknown arguments: {:s}".format(cmd_args[0])) 828 task_list.append(tval) 829 830 for tval in task_list: 831 print(GetTaskSummary.header + " " + GetProcSummary.header) 832 pval = GetProcFromTask(tval) 833 print(GetTaskSummary(tval) +" "+ GetProcSummary(pval)) 834 835# EndMacro: showtask 836 837# Macro: showpid 838 839@lldb_command('showpid') 840def ShowPid(cmd_args=None): 841 """ Routine to print a summary listing of task corresponding to given pid 842 Usage: showpid <pid value> 843 """ 844 if not cmd_args: 845 raise ArgumentError("No arguments passed") 846 pidval = ArgumentStringToInt(cmd_args[0]) 847 for t in kern.tasks: 848 pval = GetProcFromTask(t) 849 if pval and GetProcPID(pval) == pidval: 850 print(GetTaskSummary.header + " " + GetProcSummary.header) 851 print(GetTaskSummary(t) + " " + GetProcSummary(pval)) 852 break 853 854# EndMacro: showpid 855 856# Macro: showproc 857 858@lldb_command('showproc') 859def ShowProc(cmd_args=None): 860 """ Routine to print a summary listing of task corresponding to given proc 861 Usage: showproc <address of proc> 862 """ 863 if not cmd_args: 864 raise ArgumentError("No arguments passed") 865 pval = kern.GetValueFromAddress(cmd_args[0], 'proc *') 866 if not pval: 867 print("unknown arguments:", str(cmd_args)) 868 return False 869 print(GetTaskSummary.header + " " + GetProcSummary.header) 870 tval = GetTaskFromProc(pval) 871 print(GetTaskSummary(tval) + " " + GetProcSummary(pval)) 872 873# EndMacro: showproc 874 875# Macro: showprocinfo 876 877@lldb_command('showprocinfo') 878def ShowProcInfo(cmd_args=None): 879 """ Routine to display name, pid, parent & task for the given proc address 880 It also shows the Cred, Flags and state of the process 881 Usage: showprocinfo <address of proc> 882 """ 883 if not cmd_args: 884 raise ArgumentError("No arguments passed") 885 pval = kern.GetValueFromAddress(cmd_args[0], 'proc *') 886 if not pval: 887 print("unknown arguments:", str(cmd_args)) 888 return False 889 print(GetProcInfo(pval)) 890 891# EndMacro: showprocinfo 892 893#Macro: showprocfiles 894 895@lldb_command('showprocfiles') 896def ShowProcFiles(cmd_args=None): 897 """ Given a proc_t pointer, display the list of open file descriptors for the referenced process. 898 Usage: showprocfiles <proc_t> 899 """ 900 if not cmd_args: 901 print(ShowProcFiles.__doc__) 902 return 903 proc = kern.GetValueFromAddress(cmd_args[0], 'proc_t') 904 proc_filedesc = addressof(proc.p_fd) 905 proc_ofiles = proc_filedesc.fd_ofiles 906 if unsigned(proc_ofiles) == 0: 907 print('No open files for proc {0: <s}'.format(cmd_args[0])) 908 return 909 print("{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO')) 910 print("{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("")) 911 912 for fd in range(0, unsigned(proc_filedesc.fd_afterlast)): 913 if unsigned(proc_ofiles[fd]) != 0: 914 out_str = '' 915 proc_fd_flags = proc_ofiles[fd].fp_flags 916 proc_fd_fglob = proc_ofiles[fd].fp_glob 917 proc_fd_fglob_fg_data = Cast(proc_fd_fglob.fg_data, 'void *') 918 out_str += "{0: <5d} ".format(fd) 919 out_str += "{0: <#18x} ".format(unsigned(proc_fd_fglob)) 920 out_str += "0x{0:0>8x} ".format(unsigned(proc_fd_flags)) 921 proc_fd_ftype = unsigned(proc_fd_fglob.fg_ops.fo_type) 922 if proc_fd_ftype in xnudefines.filetype_strings: 923 out_str += "{0: <8s} ".format(xnudefines.filetype_strings[proc_fd_ftype]) 924 else: 925 out_str += "?: {0: <5d} ".format(proc_fd_ftype) 926 out_str += "{0: <#18x} ".format(unsigned(proc_fd_fglob_fg_data)) 927 if proc_fd_ftype == 1: 928 fd_name = Cast(proc_fd_fglob_fg_data, 'struct vnode *').v_name 929 out_str += "{0: <64s}".format(fd_name) 930 out_str += "\n" 931 print(out_str) 932 933#EndMacro: showprocfiles 934 935#Macro: showtty 936 937@lldb_command('showtty') 938def ShowTTY(cmd_args=None): 939 """ Display information about a struct tty 940 Usage: showtty <tty struct> 941 """ 942 if not cmd_args: 943 print(ShowTTY.__doc__) 944 return 945 946 tty = kern.GetValueFromAddress(cmd_args[0], 'struct tty *') 947 print("TTY structure at: {0: <s}".format(cmd_args[0])) 948 print("Last input to raw queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty.t_rawq.c_cs), tty.t_rawq.c_cs)) 949 print("Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty.t_canq.c_cs), tty.t_canq.c_cs)) 950 print("Last output data: {0: <#18x} \"{1: <s}\"".format(unsigned(tty.t_outq.c_cs), tty.t_outq.c_cs)) 951 tty_state_info = [ 952 ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'], 953 ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'], 954 ['', 'TS_BUSY (Draining output)'], 955 ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'], 956 ['', 'TS_FLUSH (Outq has been flushed during DMA)'], 957 ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'], 958 ['', 'TS_TBLOCK (Further input blocked)'], 959 ['', 'TS_TIMEOUT (Wait for output char processing)'], 960 ['', 'TS_TTSTOP (Output paused)'], 961 ['', 'TS_WOPEN (Open in progress)'], 962 ['', 'TS_XCLUDE (Tty requires exclusivity)'], 963 ['', 'TS_BKSL (State for lowercase \\ work)'], 964 ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'], 965 ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'], 966 ['', 'TS_LNCH (Next character is literal)'], 967 ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'], 968 ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'], 969 ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'], 970 ['', 'TS_SNOOP (Device is being snooped on)'], 971 ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'], 972 ['', 'TS_ZOMBIE (Connection lost)'], 973 ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'], 974 ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'], 975 ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)'] 976 ] 977 index = 0 978 mask = 0x1 979 tty_state = unsigned(tty.t_state) 980 print("State:") 981 while index < 24: 982 if tty_state & mask != 0: 983 if len(tty_state_info[index][1]) > 0: 984 print('\t' + tty_state_info[index][1]) 985 else: 986 if len(tty_state_info[index][0]) > 0: 987 print('\t' + tty_state_info[index][0]) 988 index += 1 989 mask = mask << 1 990 print("Flags: 0x{0:0>8x}".format(unsigned(tty.t_flags))) 991 print("Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty.t_pgrp))) 992 print("Enclosing session: 0x{0:0>16x}".format(unsigned(tty.t_session))) 993 print("Termios:") 994 print("\tInput Flags: 0x{0:0>8x}".format(unsigned(tty.t_termios.c_iflag))) 995 print("\tOutput Flags: 0x{0:0>8x}".format(unsigned(tty.t_termios.c_oflag))) 996 print("\tControl Flags: 0x{0:0>8x}".format(unsigned(tty.t_termios.c_cflag))) 997 print("\tLocal Flags: 0x{0:0>8x}".format(unsigned(tty.t_termios.c_lflag))) 998 print("\tInput Speed: {0: <8d}".format(tty.t_termios.c_ispeed)) 999 print("\tOutput Speed: {0: <8d}".format(tty.t_termios.c_ospeed)) 1000 print("High Watermark: {0: <d} bytes".format(tty.t_hiwat)) 1001 print("Low Watermark : {0: <d} bytes".format(tty.t_lowat)) 1002 1003#EndMacro: showtty 1004 1005#Macro showallttydevs 1006 1007@lldb_command('showallttydevs') 1008def ShowAllTTYDevs(cmd_args=[], cmd_options={}): 1009 """ Show a list of ttydevs registered in the system. 1010 Usage: 1011 (lldb)showallttydevs 1012 """ 1013 tty_dev_head = kern.globals.tty_dev_head 1014 tty_dev = tty_dev_head 1015 print(GetTTYDevSummary.header) 1016 while unsigned(tty_dev) != 0: 1017 print(GetTTYDevSummary(tty_dev)) 1018 tty_dev = tty_dev.next 1019 return "" 1020 1021#EndMacro: showallttydevs 1022 1023#Macro: dumpthread_terminate_queue 1024 1025@lldb_command('dumpthread_terminate_queue', fancy=True) 1026def DumpThreadTerminateQueue(cmd_args=None, cmd_options={}, O=None): 1027 """ Displays the contents of the specified call_entry queue. 1028 Usage: dumpthread_terminate_queue 1029 """ 1030 1031 count = 0 1032 with O.table(GetThreadSummary.header): 1033 for th in IterateMPSCQueue(addressof(kern.globals.thread_terminate_queue.mpd_queue), 'struct thread', 'mpsc_links'): 1034 print(GetThreadSummary(th, O=O)) 1035 count += 1 1036 print("{0: <d} entries!".format(count)) 1037 1038#EndMacro: dumpthread_terminate_queue 1039 1040#Macro: dumpcrashed_thread_queue 1041 1042@lldb_command('dumpcrashed_thread_queue', fancy=True) 1043def DumpCrashedThreadsQueue(cmd_args=None, cmd_options={}, O=None): 1044 """ Displays the contents of the specified call_entry queue. 1045 Usage: dumpcrashed_thread_queue 1046 """ 1047 1048 count = 0 1049 with O.table(GetThreadSummary.header): 1050 for th in IterateQueue(addressof(kern.globals.crashed_threads_queue), 'struct thread *', 'q_link'): 1051 print(GetThreadSummary(th), O=O) 1052 count += 1 1053 print("{0: <d} entries!".format(count)) 1054 1055#EndMacro: dumpcrashed_thread_queue 1056 1057#Macro: dumpcallqueue 1058 1059@lldb_command('dumpcallqueue') 1060def DumpCallQueue(cmd_args=None): 1061 """ Displays the contents of the specified call_entry queue. 1062 Usage: dumpcallqueue <queue_head_t *> 1063 """ 1064 if not cmd_args: 1065 raise ArgumentError("Invalid arguments") 1066 1067 print("{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC')) 1068 callhead = kern.GetValueFromAddress(cmd_args[0], 'queue_head_t *') 1069 count = 0 1070 for callentry in IterateQueue(callhead, 'struct call_entry *', 'q_link'): 1071 print("{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format( 1072 unsigned(callentry), unsigned(callentry.param0), unsigned(callentry.param1), 1073 unsigned(callentry.deadline), unsigned(callentry.func))) 1074 count += 1 1075 print("{0: <d} entries!".format(count)) 1076 1077#EndMacro: dumpcallqueue 1078 1079@lldb_command('showalltasklogicalwrites') 1080def ShowAllTaskIOStats(cmd_args=None): 1081 """ Commad to print I/O stats for all tasks 1082 """ 1083 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")) 1084 for t in kern.tasks: 1085 pval = GetProcFromTask(t) 1086 print("{0: <#18x} {1: >20d} {2: >20d} {3: >20d} {4: >20d} {5: <20s} {6: <20s} {7: <20s} {8: <20s} {9: <20s}".format(t, 1087 t.task_writes_counters_internal.task_immediate_writes, 1088 t.task_writes_counters_internal.task_deferred_writes, 1089 t.task_writes_counters_internal.task_invalidated_writes, 1090 t.task_writes_counters_internal.task_metadata_writes, 1091 t.task_writes_counters_external.task_immediate_writes, 1092 t.task_writes_counters_external.task_deferred_writes, 1093 t.task_writes_counters_external.task_invalidated_writes, 1094 t.task_writes_counters_external.task_metadata_writes, 1095 GetProcName(pval))) 1096 1097 1098@lldb_command('showalltasks','C', fancy=True) 1099def ShowAllTasks(cmd_args=None, cmd_options={}, O=None): 1100 """ Routine to print a summary listing of all the tasks 1101 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items" 1102 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung 1103 io_policy -> RAGE - rapid aging of vnodes requested 1104 NORM - normal I/O explicitly requested (this is the default) 1105 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions) 1106 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes) 1107 Usage: (lldb) showalltasks -C : describe the corpse structure 1108 """ 1109 global kern 1110 extra_hdr = '' 1111 showcorpse = False 1112 if '-C' in cmd_options: 1113 showcorpse = True 1114 extra_hdr += " " + GetKCDataSummary.header 1115 1116 with O.table(GetTaskSummary.header + extra_hdr + " " + GetProcSummary.header): 1117 for t in kern.tasks: 1118 pval = GetProcFromTask(t) 1119 print(GetTaskSummary(t, showcorpse) + " " + GetProcSummary(pval)) 1120 1121 ZombTasks() 1122 1123def TaskForPmapHelper(pmap): 1124 """ Given a pmap pointer, return the task pointer which contains that 1125 address space. 1126 1127 pmap: PMAP pointer whose task to find. 1128 """ 1129 for tasklist in [kern.tasks, kern.terminated_tasks]: 1130 for task in tasklist: 1131 if kern.GetValueFromAddress(unsigned(task.map.pmap), 'pmap_t') == pmap: 1132 return task 1133 1134 return None 1135 1136@lldb_command('taskforpmap') 1137def TaskForPmap(cmd_args=None): 1138 """ Find the task whose pmap corresponds to <pmap>. 1139 Syntax: (lldb) taskforpmap <pmap> 1140 Multiple -v's can be specified for increased verbosity 1141 """ 1142 if cmd_args == None or len(cmd_args) < 1: 1143 raise ArgumentError("Too few arguments to taskforpmap.") 1144 pmap = kern.GetValueFromAddress(cmd_args[0], 'pmap_t') 1145 task = TaskForPmapHelper(pmap) 1146 1147 if task is None: 1148 print("Couldn't find task for pmap {:#x}".format(pmap)) 1149 return 1150 1151 print(GetTaskSummary.header + " " + GetProcSummary.header) 1152 pval = GetProcFromTask(task) 1153 print(GetTaskSummary(task) + " " + GetProcSummary(pval)) 1154 1155@lldb_command('showterminatedtasks') 1156def ShowTerminatedTasks(cmd_args=None): 1157 """ Routine to print a summary listing of all the terminated tasks 1158 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items" 1159 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung 1160 io_policy -> RAGE - rapid aging of vnodes requested 1161 NORM - normal I/O explicitly requested (this is the default) 1162 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions) 1163 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes) 1164 syntax: (lldb)showallterminatedtasks 1165 """ 1166 global kern 1167 print(GetTaskSummary.header + " " + GetProcSummary.header) 1168 for t in kern.terminated_tasks: 1169 1170 # If the task has been terminated it's likely that the process is 1171 # gone too. If there is no proc it may still be possible to find 1172 # the original proc name. 1173 pval = GetProcFromTask(t) 1174 if pval: 1175 psummary = GetProcSummary(pval) 1176 else: 1177 name = GetProcNameForTask(t); 1178 pslen = GetProcSummary.header.find("command"); 1179 psummary = "{0: <{indent}} {1: <s}".format("", name, indent = pslen - 1) 1180 1181 print(GetTaskSummary(t) + " " + psummary) 1182 1183 return True 1184 1185# Macro: showtaskstacks 1186 1187def ShowTaskStacks(task, O=None): 1188 """ Print a task with summary and stack information for each of its threads 1189 """ 1190 global kern 1191 print(GetTaskSummary.header + " " + GetProcSummary.header) 1192 pval = GetProcFromTask(task) 1193 print(GetTaskSummary(task) + " " + GetProcSummary(pval)) 1194 for th in IterateQueue(task.threads, 'thread *', 'task_threads'): 1195 with O.table(GetThreadSummary.header, indent=True): 1196 print(GetThreadSummary(th, O=O)) 1197 print(GetThreadBackTrace(th, prefix=" ") + "\n") 1198 1199def FindTasksByName(searchstr, ignore_case=True): 1200 """ Search the list of tasks by name. 1201 params: 1202 searchstr: str - a regex like string to search for task 1203 ignore_case: bool - If False then exact matching will be enforced 1204 returns: 1205 [] - array of task object. Empty if not found any 1206 """ 1207 re_options = 0 1208 if ignore_case: 1209 re_options = re.IGNORECASE 1210 search_regex = re.compile(searchstr, re_options) 1211 retval = [] 1212 for t in kern.tasks: 1213 pval = GetProcFromTask(t) 1214 process_name = "{:s}".format(GetProcName(pval)) 1215 if search_regex.search(process_name): 1216 retval.append(t) 1217 return retval 1218 1219@lldb_command('showtaskstacks', 'F:', fancy=True) 1220def ShowTaskStacksCmdHelper(cmd_args=None, cmd_options={}, O=None): 1221 """ Routine to print out the stack for each thread in a task 1222 Usage: showtaskstacks <0xaddress of task> 1223 or: showtaskstacks -F launchd 1224 """ 1225 1226 if "-F" in cmd_options: 1227 find_task_str = cmd_options["-F"] 1228 task_list = FindTasksByName(find_task_str) 1229 for tval in task_list: 1230 ShowTaskStacks(tval, O=O) 1231 return 1232 1233 if not cmd_args: 1234 raise ArgumentError("No arguments passed") 1235 1236 tval = kern.GetValueFromAddress(cmd_args[0], 'task *') 1237 if not tval: 1238 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args))) 1239 else: 1240 ShowTaskStacks(tval, O=O) 1241 1242# EndMacro: showtaskstacks 1243 1244def CheckTaskProcRefs(task, proc, O=None): 1245 btlib = kmemory.BTLibrary.get_shared() 1246 1247 for thread in IterateQueue(task.threads, 'thread *', 'task_threads'): 1248 uthread = GetBSDThread(thread) 1249 refcount = int(uthread.uu_proc_refcount) 1250 uu_ref_info = uthread.uu_proc_ref_info 1251 if int(uu_ref_info) == 0: 1252 continue 1253 uu_ref_index = int(uu_ref_info.upri_pindex) 1254 if refcount == 0: 1255 continue 1256 for ref in range(0, uu_ref_index): 1257 if unsigned(uu_ref_info.upri_proc_ps[ref]) == unsigned(proc): 1258 print(GetTaskSummary.header + " " + GetProcSummary.header) 1259 pval = GetProcFromTask(task) 1260 print(GetTaskSummary(task) + " " + GetProcSummary(pval)) 1261 with O.table(GetThreadSummary.header, indent=True): 1262 print(GetThreadSummary(thread, O=O)) 1263 1264 bts = btlib.get_stack(unsigned(uu_ref_info.upri_proc_stacks[ref])) 1265 print(*bts.symbolicated_frames(), sep="\n") 1266 1267@lldb_command('showprocrefs', fancy=True) 1268def ShowProcRefs(cmd_args=None, cmd_options={}, O=None): 1269 """ Display information on threads/BTs that could be holding a reference on the specified proc 1270 NOTE: We can't say affirmatively if any of these references are still held since 1271 there's no way to pair references with drop-refs in the current infrastructure. 1272 Usage: showprocrefs <proc> 1273 """ 1274 if cmd_args == None or len(cmd_args) < 1: 1275 raise ArgumentError("No arguments passed") 1276 1277 proc = kern.GetValueFromAddress(cmd_args[0], 'proc *') 1278 1279 for t in kern.tasks: 1280 CheckTaskProcRefs(t, proc, O=O) 1281 for t in kern.terminated_tasks: 1282 CheckTaskProcRefs(t, proc, O=O) 1283 1284@lldb_command('showallthreads', fancy=True) 1285def ShowAllThreads(cmd_args=None, cmd_options={}, O=None): 1286 """ Display info about all threads in the system 1287 """ 1288 1289 # Terminated threads get prefixed with a 'T' 1290 def ShowTaskTerminatedThreads(task, O=O): 1291 tlist = tmap.get(unsigned(task), []) 1292 for thval in tlist: 1293 print("T\t" + GetThreadSummary(thval, O=O)) 1294 1295 # Task -> [thread, ..] map of terminated threads 1296 tmap = defaultdict(list) 1297 for thr in kern.terminated_threads: 1298 tmap[unsigned(thr.t_tro.tro_task)].append(thr) 1299 1300 for t in kern.tasks: 1301 ShowTaskThreads([str(int(t))], O=O) 1302 ShowTaskTerminatedThreads(t, O=O) 1303 print(" \n") 1304 1305 for t in kern.terminated_tasks: 1306 print("Terminated: \n") 1307 ShowTaskThreads([str(int(t))], O=O) 1308 ShowTaskTerminatedThreads(t, O=O) 1309 print(" \n") 1310 1311 return 1312 1313@lldb_command('showterminatedthreads', fancy=True) 1314def ShowTerminatedThreads(cmd_args=None, cmd_options={}, O=None): 1315 """ Display info about all terminated threads in the system 1316 """ 1317 1318 with O.table(GetThreadSummary.header, indent=True): 1319 for t in kern.terminated_threads: 1320 print(GetThreadSummary(t, O=O)) 1321 1322 1323@lldb_command('showtaskthreads', "F:", fancy=True) 1324def ShowTaskThreads(cmd_args = None, cmd_options={}, O=None): 1325 """ List the threads of a task. 1326 Usage: showtaskthreads <task-ptr> 1327 or: showtaskthreads -F <name> 1328 """ 1329 task_list = [] 1330 if "-F" in cmd_options: 1331 task_list = FindTasksByName(cmd_options["-F"]) 1332 elif cmd_args: 1333 t = kern.GetValueFromAddress(cmd_args[0], 'task *') 1334 task_list = [t] 1335 else: 1336 raise ArgumentError("No arguments passed") 1337 1338 for task in task_list: 1339 print(GetTaskSummary.header + " " + GetProcSummary.header) 1340 pval = GetProcFromTask(task) 1341 print(GetTaskSummary(task) + " " + GetProcSummary(pval)) 1342 with O.table(GetThreadSummary.header, indent=True): 1343 for thval in IterateQueue(task.threads, 'thread *', 'task_threads'): 1344 print(GetThreadSummary(thval, O=O)) 1345 return 1346 1347@lldb_command('showact', fancy=True) 1348def ShowAct(cmd_args=None, cmd_options={}, O=None): 1349 """ Routine to print out the state of a specific thread. 1350 usage: showact <activation> 1351 """ 1352 if not cmd_args: 1353 raise ArgumentError("No arguments passed") 1354 threadval = kern.GetValueFromAddress(cmd_args[0], 'thread *') 1355 with O.table(GetThreadSummary.header): 1356 print(GetThreadSummary(threadval, O=O)) 1357 1358@lldb_command('showactstack', fancy=True) 1359def ShowActStack(cmd_args=None, cmd_options={}, O=None): 1360 """ Routine to print out the stack of a specific thread. 1361 usage: showactstack <activation> 1362 """ 1363 if not cmd_args: 1364 raise ArgumentError("No arguments passed") 1365 threadval = kern.GetValueFromAddress(cmd_args[0], 'thread *') 1366 with O.table(GetThreadSummary.header): 1367 print(GetThreadSummary(threadval, O=O)) 1368 print(GetThreadBackTrace(threadval, prefix="\t")) 1369 return 1370 1371@lldb_command('switchtoact', fancy=True) 1372def SwitchToAct(cmd_args=None, cmd_options={}, O=None): 1373 """ Switch to different context specified by activation 1374 This command allows gdb to examine the execution context and call 1375 stack for the specified activation. For example, to view the backtrace 1376 for an activation issue "switchtoact <address>", followed by "bt". 1377 Before resuming execution, issue a "resetctx" command, to 1378 return to the original execution context. 1379 """ 1380 if cmd_args is None or len(cmd_args) < 1: 1381 raise ArgumentError("No arguments passed") 1382 thval = kern.GetValueFromAddress(cmd_args[0], 'thread *') 1383 lldbthread = GetLLDBThreadForKernelThread(thval) 1384 with O.table(GetThreadSummary.header): 1385 print(GetThreadSummary(thval, O=O)) 1386 LazyTarget.GetProcess().selected_thread = lldbthread 1387 if not LazyTarget.GetProcess().SetSelectedThread(lldbthread): 1388 print("Failed to switch thread.") 1389 return 1390 1391@lldb_command('switchtoregs') 1392def SwitchToRegs(cmd_args=None): 1393 """ Routine to switch to a register state. 1394 Usage: (lldb) switchtoregs <struct arm_saved_state[64] *> 1395 This command creates a fake thread in lldb with the saved register state. 1396 Note: This command ONLY works for ARM based kernel setup. 1397 """ 1398 1399 if cmd_args == None or len(cmd_args) < 1: 1400 raise ArgumentError("No arguments passed") 1401 1402 lldb_process = LazyTarget.GetProcess() 1403 1404 saved_state = ArgumentStringToInt(cmd_args[0]) 1405 # any change to this logic requires change in operating_system.py as well 1406 fake_thread_id = 0xdead0000 | (saved_state & ~0xffff0000) 1407 fake_thread_id = fake_thread_id & 0xdeadffff 1408 lldb_process.CreateOSPluginThread(0xdeadbeef, saved_state) 1409 lldbthread = lldb_process.GetThreadByID(int(fake_thread_id)) 1410 1411 if not lldbthread.IsValid(): 1412 print("Failed to create thread") 1413 return 1414 1415 lldb_process.selected_thread = lldbthread 1416 if not lldb_process.SetSelectedThread(lldbthread): 1417 print("Failed to switch thread") 1418 print("Switched to Fake thread created from register state at {:#x}".format( 1419 saved_state)) 1420 1421 1422# Macro: showallstacks 1423@lldb_command('showallstacks', fancy=True) 1424def ShowAllStacks(cmd_args=None, cmd_options={}, O=None): 1425 """Routine to print out the stack for each thread in the system. 1426 """ 1427 for t in kern.tasks: 1428 ShowTaskStacks(t, O=O) 1429 print(" \n") 1430 ZombStacks(O=O) 1431 1432# EndMacro: showallstacks 1433 1434# Macro: showcurrentstacks 1435@lldb_command('showcurrentstacks', fancy=True) 1436def ShowCurrentStacks(cmd_args=None, cmd_options={}, O=None): 1437 """ Routine to print out the thread running on each cpu (incl. its stack) 1438 """ 1439 processor_list = kern.GetGlobalVariable('processor_list') 1440 current_processor = processor_list 1441 while unsigned(current_processor) > 0: 1442 print("\n" + GetProcessorSummary(current_processor)) 1443 active_thread = current_processor.active_thread 1444 if unsigned(active_thread) != 0: 1445 task_val = active_thread.t_tro.tro_task 1446 proc_val = GetProcFromTask(task_val) 1447 print(GetTaskSummary.header + " " + GetProcSummary.header) 1448 print(GetTaskSummary(task_val) + " " + GetProcSummary(proc_val)) 1449 with O.table(GetThreadSummary.header, indent=True): 1450 print(GetThreadSummary(active_thread, O=O)) 1451 print("\tBacktrace:") 1452 print(GetThreadBackTrace(active_thread, prefix="\t")) 1453 current_processor = current_processor.processor_list 1454 return 1455# EndMacro: showcurrentstacks 1456 1457@lldb_command('showcurrentthreads', fancy=True) 1458def ShowCurrentThreads(cmd_args=None, cmd_options={}, O=None): 1459 """ Display info about threads running on each cpu """ 1460 processor_list = kern.GetGlobalVariable('processor_list') 1461 current_processor = processor_list 1462 while unsigned(current_processor) > 0: 1463 print(GetProcessorSummary(current_processor)) 1464 active_thread = current_processor.active_thread 1465 if unsigned(active_thread) != 0 : 1466 task_val = active_thread.t_tro.tro_task 1467 proc_val = GetProcFromTask(task_val) 1468 print(GetTaskSummary.header + " " + GetProcSummary.header) 1469 print(GetTaskSummary(task_val) + " " + GetProcSummary(proc_val)) 1470 with O.table(GetThreadSummary.header, indent=True): 1471 print(GetThreadSummary(active_thread, O=O)) 1472 current_processor = current_processor.processor_list 1473 return 1474 1475def GetFullBackTrace(frame_addr, verbosity = vHUMAN, prefix = ""): 1476 """ Get backtrace across interrupt context. 1477 params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7) 1478 prefix - str - prefix for each line of output. 1479 1480 """ 1481 out_string = "" 1482 bt_count = 0 1483 frame_ptr = frame_addr 1484 previous_frame_ptr = 0 1485 # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header 1486 mh_execute_addr = int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16) 1487 while frame_ptr and frame_ptr != previous_frame_ptr and bt_count < 128: 1488 if (not kern.arch.startswith('arm') and frame_ptr < mh_execute_addr) or (kern.arch.startswith('arm') and frame_ptr > mh_execute_addr): 1489 break 1490 pc_val = kern.GetValueFromAddress(frame_ptr + kern.ptrsize,'uintptr_t *') 1491 pc_val = kern.StripKernelPAC(unsigned(dereference(pc_val))) 1492 out_string += prefix + GetSourceInformationForAddress(pc_val) + "\n" 1493 bt_count +=1 1494 previous_frame_ptr = frame_ptr 1495 frame_val = kern.GetValueFromAddress((frame_ptr), 'uintptr_t *') 1496 if unsigned(frame_val) == 0: 1497 break 1498 frame_ptr = unsigned(dereference(frame_val)) 1499 1500 return out_string 1501 1502@lldb_command('fullbt') 1503def FullBackTrace(cmd_args=[]): 1504 """ Show full backtrace across the interrupt boundary. 1505 Syntax: fullbt <frame ptr> 1506 Example: fullbt `$rbp` 1507 """ 1508 if len(cmd_args) < 1: 1509 print(FullBackTrace.__doc__) 1510 return False 1511 print(GetFullBackTrace(ArgumentStringToInt(cmd_args[0]), prefix="\t")) 1512 1513@lldb_command('fullbtall', fancy=True) 1514def FullBackTraceAll(cmd_args=[], cmd_options={}, O=None): 1515 """ Show full backtrace across the interrupt boundary for threads running on all processors. 1516 Syntax: fullbtall 1517 Example: fullbtall 1518 """ 1519 for processor in IterateLinkedList(kern.globals.processor_list, 'processor_list') : 1520 print("\n" + GetProcessorSummary(processor)) 1521 active_thread = processor.active_thread 1522 if unsigned(active_thread) != 0 : 1523 task_val = active_thread.t_tro.tro_task 1524 proc_val = GetProcFromTask(task_val) 1525 print(GetTaskSummary.header + " " + GetProcSummary.header) 1526 print(GetTaskSummary(task_val) + " " + GetProcSummary(proc_val)) 1527 with O.table(GetThreadSummary.header, indent=True): 1528 print(GetThreadSummary(active_thread, O=O)) 1529 print("\tBacktrace:") 1530 1531 ThreadVal = GetLLDBThreadForKernelThread(active_thread) 1532 1533 FramePtr = ThreadVal.frames[0].GetFP() 1534 1535 print(GetFullBackTrace(unsigned(FramePtr), prefix="\t")) 1536 1537 1538@lldb_command('symbolicate') 1539def SymbolicateAddress(cmd_args=[]): 1540 """ Symbolicate an address for symbol information from loaded symbols 1541 Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr" 1542 """ 1543 if len(cmd_args) < 1: 1544 print("Invalid address.\nSyntax: symbolicate <address>") 1545 return False 1546 print(GetSourceInformationForAddress(ArgumentStringToInt(cmd_args[0]))) 1547 return True 1548 1549@lldb_command('showinitchild') 1550def ShowInitChild(cmd_args=None): 1551 """ Routine to print out all processes in the system 1552 which are children of init process 1553 """ 1554 headp = kern.globals.initproc.p_children 1555 for pp in IterateListEntry(headp, 'p_sibling'): 1556 print(GetProcInfo(pp)) 1557 return 1558 1559@lldb_command('showproctree') 1560def ShowProcTree(cmd_args=None): 1561 """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes. 1562 If no argument is given, showproctree will print all the processes in the system. 1563 If pid is specified, showproctree prints all the descendants of the indicated process 1564 """ 1565 search_pid = 0 1566 if cmd_args: 1567 search_pid = ArgumentStringToInt(cmd_args[0]) 1568 1569 if search_pid < 0: 1570 print("pid specified must be a positive number") 1571 print(ShowProcTree.__doc__) 1572 return 1573 1574 hdr_format = "{0: <6s} {1: <14s} {2: <9s}\n" 1575 out_string = hdr_format.format("PID", "PROCESS", "POINTER") 1576 out_string += hdr_format.format('='*3, '='*7, '='*7) 1577 proc = GetProcForPid(search_pid) 1578 out_string += "{0: <6d} {1: <32s} [ {2: #019x} ]\n".format( 1579 proc.p_ppid, GetProcName(proc.p_pptr), unsigned(proc.p_pptr)) 1580 out_string += "|--{0: <6d} {1: <32s} [ {2: #019x} ]\n".format( 1581 GetProcPID(proc), GetProcName(proc), unsigned(proc)) 1582 print(out_string) 1583 ShowProcTreeRecurse(proc, "| ") 1584 1585def ShowProcTreeRecurse(proc, prefix=""): 1586 """ Prints descendants of a given proc in hierarchial tree form 1587 params: 1588 proc : core.value representing a struct proc * in the kernel 1589 returns: 1590 str : String containing info about a given proc and its descendants in tree form 1591 """ 1592 if proc.p_childrencnt > 0: 1593 head_ptr = proc.p_children.lh_first 1594 1595 for p in IterateListEntry(proc.p_children, 'p_sibling'): 1596 print(prefix + "|--{0: <6d} {1: <32s} [ {2: #019x} ]\n".format( 1597 GetProcPID(p), GetProcName(p), unsigned(p))) 1598 ShowProcTreeRecurse(p, prefix + "| ") 1599 1600@lldb_command('showthreadfortid', fancy=True) 1601def ShowThreadForTid(cmd_args=None, O=None): 1602 """ The thread structure contains a unique thread_id value for each thread. 1603 This command is used to retrieve the address of the thread structure(thread_t) 1604 corresponding to a given thread_id. 1605 """ 1606 if not cmd_args: 1607 print("Please provide thread_t whose tid you'd like to look up") 1608 print(ShowThreadForTid.__doc__) 1609 return 1610 search_tid = ArgumentStringToInt(cmd_args[0]) 1611 for taskp in kern.tasks: 1612 for actp in IterateQueue(taskp.threads, 'struct thread *', 'task_threads'): 1613 if search_tid == int(actp.thread_id): 1614 print("Found {0: #019x}".format(actp)) 1615 with O.table(GetThreadSummary.header): 1616 print(GetThreadSummary(actp, O=O)) 1617 return 1618 print("Not a valid thread_id") 1619 1620def GetProcessorSummary(processor): 1621 """ Internal function to print summary of processor 1622 params: processor - value representing struct processor * 1623 return: str - representing the details of given processor 1624 """ 1625 1626 processor_state_str = "INVALID" 1627 processor_state = int(processor.state) 1628 1629 processor_states = { 1630 0: 'OFF_LINE', 1631 1: 'SHUTDOWN', 1632 2: 'START', 1633 3: 'PENDING_OFFLINE', 1634 4: 'IDLE', 1635 5: 'DISPATCHING', 1636 6: 'RUNNING' 1637 } 1638 1639 if processor_state in processor_states: 1640 processor_state_str = "{0: <11s} ".format(processor_states[processor_state]) 1641 1642 processor_recommended_str = "" 1643 if int(processor.is_recommended) == 0: 1644 processor_recommended_str = " (not recommended)" 1645 1646 ast = 0 1647 preemption_disable = 0 1648 preemption_disable_str = "" 1649 1650 if kern.arch == 'x86_64': 1651 cpu_data = kern.globals.cpu_data_ptr[processor.cpu_id] 1652 if (cpu_data != 0) : 1653 ast = cpu_data.cpu_pending_ast 1654 preemption_disable = cpu_data.cpu_preemption_level 1655 # On arm64, it's kern.globals.CpuDataEntries[processor.cpu_id].cpu_data_vaddr 1656 # but LLDB can't find CpuDataEntries... 1657 1658 ast_str = GetASTSummary(ast) 1659 1660 if (preemption_disable != 0) : 1661 preemption_disable_str = "Preemption Disabled" 1662 1663 processor_reasons = { 1664 0: '(REASON_NONE)', 1665 1: '(REASON_SYSTEM)', 1666 2: '(REASON_USER)', 1667 3: '(REASON_CLPC_SYSTEM)', 1668 4: '(REASON_CLPC_USER)' 1669 } 1670 1671 processor_shutdown_reason_str = ""; 1672 processor_shutdown_reason = int(processor.last_shutdown_reason) 1673 1674 if processor_state in {0, 1, 3}: 1675 processor_shutdown_reason_str = processor_reasons[processor_shutdown_reason] 1676 1677 out_str = "Processor {: <#018x} cpu_id {:>#4x} AST: {:<6s} State {:<s}{:<s}{:<s} {:<s}\n".format( 1678 processor, int(processor.cpu_id), ast_str, processor_state_str, processor_shutdown_reason_str, 1679 processor_recommended_str, preemption_disable_str) 1680 return out_str 1681 1682ledger_limit_infinity = (uint64_t(0x1).value << 63) - 1 1683 1684def GetLedgerEntryIndex(template, name): 1685 i = 0 1686 while i != template.lt_cnt: 1687 if str(template.lt_entries[i].et_key) == name: 1688 return i 1689 i = i + 1 1690 return -1 1691 1692def GetLedgerEntryWithTemplate(ledger_template, ledgerp, i): 1693 """ Internal function to get internals of a ledger entry (*not* a ledger itself) 1694 params: ledger_template - value representing struct ledger_template_t for the task or thread 1695 ledgerp - value representing ledger pointer 1696 i - index in ledger 1697 return: entry - entry dictionary 1698 """ 1699 lf_refill_scheduled = 0x0400 1700 lf_tracking_max = 0x4000 1701 1702 now = unsigned(kern.globals.sched_tick) // 20 1703 lim_pct = 0 1704 1705 entry = {} 1706 1707 et = ledger_template.lt_entries[i] 1708 entry["key"] = str(et.et_key) 1709 if et.et_size == sizeof("struct ledger_entry_small"): 1710 les = ledgerp.l_entries[et.et_offset] 1711 entry["credit"] = unsigned(les.les_credit) 1712 entry["debit"] = 0 1713 entry["flags"] = int(les.les_flags) 1714 entry["limit"] = ledger_limit_infinity 1715 elif et.et_size == sizeof("struct ledger_entry"): 1716 le = Cast(addressof(ledgerp.l_entries[et.et_offset]), "struct ledger_entry *") 1717 entry["credit"] = unsigned(le.le_credit) 1718 entry["debit"] = unsigned(le.le_debit) 1719 if (le.le_flags & lf_tracking_max): 1720 if hasattr(le._le._le_max, "le_interval_max"): 1721 entry["interval_max"] = unsigned(le._le._le_max.le_interval_max) 1722 entry["lifetime_max"] = unsigned(le._le._le_max.le_lifetime_max) 1723 1724 entry["limit"] = unsigned(le.le_limit) 1725 1726 if (le.le_flags & lf_refill_scheduled): 1727 entry["refill_period"] = unsigned (le._le.le_refill.le_refill_period) 1728 1729 if (unsigned(le.le_warn_percent) < 65535): 1730 entry["warn_percent"] = unsigned (le.le_warn_percent * 100 / 65536) 1731 entry["flags"] = int(le.le_flags) 1732 entry["diag_threshold_scaled"] = int(le.le_diag_threshold_scaled) 1733 else: 1734 return None 1735 1736 entry["balance"] = entry["credit"] - entry["debit"] 1737 return entry 1738 1739def GetLedgerEntryWithName(ledger_template, ledger, name): 1740 idx = GetLedgerEntryIndex(ledger_template, name) 1741 assert(idx != -1) 1742 return GetLedgerEntryWithTemplate(ledger_template, ledger, idx) 1743 1744def FormatLedgerEntrySummary(entry, i, show_footprint_interval_max=False): 1745 """ internal function to format a ledger entry into a string 1746 params: entry - A python dictionary containing the ledger entry 1747 return: str - formatted output information of ledger entries 1748 """ 1749 out_str = '' 1750 out_str += "{: >32s} {:<2d}:".format(entry["key"], i) 1751 out_str += "{: >15d} ".format(entry["balance"]) 1752 1753 if (show_footprint_interval_max): 1754 if "interval_max" in entry: 1755 out_str += "{:12d} ".format(entry["interval_max"]) 1756 else: 1757 out_str += " - " 1758 1759 if "lifetime_max" in entry: 1760 out_str += "{:14d} ".format(entry["lifetime_max"]) 1761 else: 1762 out_str += " - " 1763 1764 out_str += "{:12d} {:12d} ".format(entry["credit"], entry["debit"]) 1765 if entry.get('limit', unsigned(ledger_limit_infinity)) != unsigned(ledger_limit_infinity): 1766 out_str += "{:12d} ".format(unsigned(entry["limit"])) 1767 else: 1768 out_str += " - " 1769 1770 if "refill_period" in entry: 1771 out_str += "{:15d} ".format(entry["refill_period"]) 1772 if entry["refill_period"] != 0: 1773 out_str += "{:9d} ".format((entry["limit"] * 100) // entry["refill_period"]) 1774 else: 1775 out_str += "XXXXX - " 1776 else: 1777 out_str += " - " 1778 out_str += " - " 1779 1780 if "warn_percent" in entry: 1781 out_str += "{:9d} ".format(entry["warn_percent"]) 1782 else: 1783 out_str += " - " 1784 1785 if "limit" in entry: 1786 if entry["balance"] > entry["limit"]: 1787 out_str += " X " 1788 else: 1789 out_str += " " 1790 else: 1791 out_str += " " 1792 1793 out_str += "{:#8x}\n".format(entry["flags"]) 1794 return out_str 1795 1796def GetLedgerEntrySummary(ledger_template, ledger, i, show_footprint_interval_max=False): 1797 """ internal function to get internals of a ledger entry (*not* a ledger itself) 1798 params: ledger_template - value representing struct ledger_template_t for the task or thread 1799 ledger - value representing ledger pointer 1800 return: str - formatted output information of ledger entries 1801 """ 1802 entry = GetLedgerEntryWithTemplate(ledger_template, ledger, i) 1803 return FormatLedgerEntrySummary(entry, i) 1804 1805 1806def GetThreadLedgers(thread_val): 1807 """ Internal function to get a summary of ledger entries for the given thread 1808 params: thread_val - value representing struct thread * 1809 return: thread - python dictionary containing threads's ledger entries. This can 1810 be printed directly with FormatThreadLedgerSummmary or outputted as json. 1811 """ 1812 thread = {} 1813 thread["address"] = unsigned(thread_val) 1814 ledgerp = thread_val.t_threadledger 1815 thread["entries"] = [] 1816 if ledgerp: 1817 i = 0 1818 while i != ledgerp.l_template.lt_cnt: 1819 thread["entries"].append(GetLedgerEntryWithTemplate(kern.globals.thread_ledger_template, 1820 ledgerp, i)) 1821 i = i + 1 1822 return thread 1823 1824def FormatThreadLedgerSummary(thread): 1825 """ Internal function to print a thread's ledger entries 1826 params: thread - python dictionary containing thread's ledger entries 1827 return: str - formatted output information for ledger entries of the input thread 1828 """ 1829 out_str = " [{:#08x}]\n".format(thread["address"]) 1830 entries = thread["entries"] 1831 for i, entry in enumerate(entries): 1832 out_str += FormatLedgerEntrySummary(entry, i) 1833 return out_str 1834 1835def GetTaskLedgers(task_val): 1836 """ Internal function to get summary of ledger entries from the task and its threads 1837 params: task_val - value representing struct task * 1838 return: task - python dictionary containing tasks's ledger entries. This can 1839 be printed directly with FormatTaskLedgerSummary or outputted as json. 1840 """ 1841 task_ledgerp = task_val.ledger 1842 i = 0 1843 tasks = [] 1844 task = {} 1845 task["address"] = unsigned(task_val) 1846 1847 pval = GetProcFromTask(task_val) 1848 if pval: 1849 task["name"] = GetProcName(pval) 1850 task["pid"] = int(GetProcPID(pval)) 1851 1852 task["entries"] = [] 1853 while i != task_ledgerp.l_template.lt_cnt: 1854 task["entries"].append(GetLedgerEntryWithTemplate(kern.globals.task_ledger_template, task_ledgerp, i)) 1855 i = i + 1 1856 1857 # Now walk threads 1858 task["threads"] = [] 1859 for thval in IterateQueue(task_val.threads, 'thread *', 'task_threads'): 1860 task["threads"].append(GetThreadLedgers(thval)) 1861 1862 return task 1863 1864@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( 1865 "task [thread]", "entry", "#", "balance", "lifetime_max", "credit", 1866 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags")) 1867def FormatTaskLedgerSummary(task, show_footprint_interval_max=False): 1868 """ Internal function to get summary of ledger entries from the task and its threads 1869 params: task_val - value representing struct task * 1870 return: str - formatted output information for ledger entries of the input task 1871 """ 1872 out_str = '' 1873 out_str += "{: #08x} ".format(task["address"]) 1874 if "name" in task: 1875 out_str += "{: <5s}:\n".format(task["name"]) 1876 else: 1877 out_str += "Invalid process\n" 1878 1879 for i, entry in enumerate(task["entries"]): 1880 out_str += FormatLedgerEntrySummary(entry, i, show_footprint_interval_max) 1881 1882 for thread in task["threads"]: 1883 out_str += FormatThreadLedgerSummary(thread) 1884 return out_str 1885 1886 1887# Macro: showtaskledgers 1888 1889@lldb_command('showtaskledgers', 'JF:I') 1890def ShowTaskLedgers(cmd_args=None, cmd_options={}): 1891 """ Routine to print a summary of ledger entries for the task and all of its threads 1892 or : showtaskledgers [ -I ] [-J] [ -F ] <task> 1893 options: 1894 -I: show footprint interval max (DEV/DEBUG only) 1895 -F: specify task via name instead of address 1896 -J: output json 1897 - 1898 """ 1899 print_json = False 1900 if "-F" in cmd_options: 1901 task_list = FindTasksByName(cmd_options["-F"]) 1902 for tval in task_list: 1903 print(FormatTaskLedgerSummary.header) 1904 ledgers = GetTaskLedgers(tval) 1905 print(FormatTaskLedgerSummary(ledgers)) 1906 return 1907 if "-J" in cmd_options: 1908 print_json = True 1909 1910 if not cmd_args: 1911 raise ArgumentError("No arguments passed.") 1912 show_footprint_interval_max = False 1913 if "-I" in cmd_options: 1914 show_footprint_interval_max = True 1915 tval = kern.GetValueFromAddress(cmd_args[0], 'task *') 1916 if not tval: 1917 raise ArgumentError("unknown arguments: %r" %cmd_args) 1918 ledgers = GetTaskLedgers(tval) 1919 if print_json: 1920 print(json.dumps(ledgers)) 1921 else: 1922 if (show_footprint_interval_max): 1923 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( 1924 "task [thread]", "entry", "#", "balance", "intrvl_max", "lifetime_max", "credit", 1925 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags")) 1926 else: 1927 print(FormatTaskLedgerSummary.header) 1928 print(FormatTaskLedgerSummary(ledgers, show_footprint_interval_max)) 1929 1930# EndMacro: showtaskledgers 1931 1932# Macro: showalltaskledgers 1933 1934@lldb_command('showalltaskledgers', "J") 1935def ShowAllTaskLedgers(cmd_args=None, cmd_options={}): 1936 """ Routine to print a summary of ledger entries for all tasks and respective threads 1937 Usage: showalltaskledgers [-J] 1938 -J : Output json 1939 """ 1940 print_json = False 1941 if "-J" in cmd_options: 1942 print_json = True 1943 tasks = [] 1944 for t in kern.tasks: 1945 task_val = unsigned(t) 1946 if not print_json: 1947 ShowTaskLedgers([task_val], cmd_options=cmd_options) 1948 else: 1949 tasks.append(GetTaskLedgers(t)) 1950 if print_json: 1951 print(json.dumps(tasks)) 1952 1953# EndMacro: showalltaskledgers 1954 1955# Macro: showprocuuidpolicytable 1956 1957@lldb_type_summary(['proc_uuid_policy_entry']) 1958@header("{0: <36s} {1: <10s}".format("uuid", "flags")) 1959def GetProcUUIDPolicyEntrySummary(entry): 1960 """ Summarizes the important fields in proc_uuid_policy_entry structure. 1961 params: entry: value - value object representing an entry 1962 returns: str - summary of the entry 1963 """ 1964 data = [] 1965 for i in range(16): 1966 data.append(int(entry.uuid[i])) 1967 flags = unsigned(entry.flags) 1968 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) 1969 return out_string 1970 1971@lldb_command('showprocuuidpolicytable') 1972def ShowProcUUIDPolicyTable(cmd_args=None): 1973 """ Routine to print the proc UUID policy table 1974 Usage: showprocuuidpolicytable 1975 """ 1976 hashslots = unsigned(kern.globals.proc_uuid_policy_hash_mask) 1977 print("{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary.header) 1978 for i in range(0, hashslots+1): 1979 headp = addressof(kern.globals.proc_uuid_policy_hashtbl[i]) 1980 entrynum = 0 1981 for entry in IterateListEntry(headp, 'entries'): 1982 print("{0: >2d}.{1: <5d} ".format(i, entrynum) + GetProcUUIDPolicyEntrySummary(entry)) 1983 entrynum += 1 1984 1985 1986# EndMacro: showprocuuidpolicytable 1987 1988@lldb_command('showalltaskpolicy') 1989def ShowAllTaskPolicy(cmd_args=None): 1990 """ 1991 Routine to print a summary listing of all the tasks 1992 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items" 1993 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung 1994 io_policy -> RAGE - rapid aging of vnodes requested 1995 NORM - normal I/O explicitly requested (this is the default) 1996 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions) 1997 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes) 1998 """ 1999 global kern 2000 print(GetTaskSummary.header + " " + GetProcSummary.header) 2001 for t in kern.tasks: 2002 pval = GetProcFromTask(t) 2003 print(GetTaskSummary(t) +" "+ GetProcSummary(pval)) 2004 requested_strings = [ 2005 ["int_darwinbg", "DBG-int"], 2006 ["ext_darwinbg", "DBG-ext"], 2007 ["int_iotier", "iotier-int"], 2008 ["ext_iotier", "iotier-ext"], 2009 ["int_iopassive", "passive-int"], 2010 ["ext_iopassive", "passive-ext"], 2011 ["bg_iotier", "bg-iotier"], 2012 ["terminated", "terminated"], 2013 ["th_pidbind_bg", "bg-pidbind"], 2014 ["t_apptype", "apptype"], 2015 ["t_boosted", "boosted"], 2016 ["t_role", "role"], 2017 ["t_tal_enabled", "tal-enabled"], 2018 ["t_base_latency_qos", "latency-base"], 2019 ["t_over_latency_qos", "latency-override"], 2020 ["t_base_through_qos", "throughput-base"], 2021 ["t_over_through_qos", "throughput-override"] 2022 ] 2023 2024 requested="" 2025 for value in requested_strings: 2026 if t.requested_policy.__getattr__(value[0]) : 2027 requested+=value[1] + ": " + str(t.requested_policy.__getattr__(value[0])) + " " 2028 else: 2029 requested+="" 2030 2031 suppression_strings = [ 2032 ["t_sup_active", "active"], 2033 ["t_sup_lowpri_cpu", "lowpri-cpu"], 2034 ["t_sup_timer", "timer-throttling"], 2035 ["t_sup_disk", "disk-throttling"], 2036 ["t_sup_cpu_limit", "cpu-limits"], 2037 ["t_sup_suspend", "suspend"], 2038 ["t_sup_bg_sockets", "bg-sockets"] 2039 ] 2040 2041 suppression="" 2042 for value in suppression_strings: 2043 if t.requested_policy.__getattr__(value[0]) : 2044 suppression+=value[1] + ": " + str(t.requested_policy.__getattr__(value[0])) + " " 2045 else: 2046 suppression+="" 2047 2048 effective_strings = [ 2049 ["darwinbg", "background"], 2050 ["lowpri_cpu", "lowpri-cpu"], 2051 ["io_tier", "iotier"], 2052 ["io_passive", "passive"], 2053 ["all_sockets_bg", "bg-allsockets"], 2054 ["new_sockets_bg", "bg-newsockets"], 2055 ["bg_iotier", "bg-iotier"], 2056 ["terminated", "terminated"], 2057 ["t_gpu_deny", "gpu-deny"], 2058 ["t_tal_engaged", "tal-engaged"], 2059 ["t_suspended", "suspended"], 2060 ["t_watchers_bg", "bg-watchers"], 2061 ["t_latency_qos", "latency-qos"], 2062 ["t_through_qos", "throughput-qos"], 2063 ["t_sup_active", "suppression-active"], 2064 ["t_role", "role"] 2065 ] 2066 2067 effective="" 2068 for value in effective_strings: 2069 if t.effective_policy.__getattr__(value[0]) : 2070 effective+=value[1] + ": " + str(t.effective_policy.__getattr__(value[0])) + " " 2071 else: 2072 effective+="" 2073 2074 print("requested: " + requested) 2075 print("suppression: " + suppression) 2076 print("effective: " + effective) 2077 2078 2079@lldb_command('showallsuspendedtasks', '') 2080def ShowSuspendedTasks(cmd_args=[], options={}): 2081 """ Show a list of suspended tasks with their process name summary. 2082 """ 2083 print(GetTaskSummary.header + ' ' + GetProcSummary.header) 2084 for t in kern.tasks: 2085 if t.suspend_count > 0: 2086 print(GetTaskSummary(t) + ' ' + GetProcSummary(GetProcFromTask(t))) 2087 return True 2088 2089# Macro: showallpte 2090@lldb_command('showallpte') 2091def ShowAllPte(cmd_args=None): 2092 """ Prints out the physical address of the pte for all tasks 2093 """ 2094 head_taskp = addressof(kern.globals.tasks) 2095 taskp = Cast(head_taskp.next, 'task *') 2096 while taskp != head_taskp: 2097 procp = GetProcFromTask(taskp) 2098 out_str = "task = {:#x} pte = {:#x}\t".format(taskp, taskp.map.pmap.ttep) 2099 if procp != 0: 2100 out_str += "{:s}\n".format(GetProcName(procp)) 2101 else: 2102 out_str += "\n" 2103 print(out_str) 2104 taskp = Cast(taskp.tasks.next, 'struct task *') 2105 2106# EndMacro: showallpte 2107 2108# Macro: showallrefcounts 2109@lldb_command('showallrefcounts') 2110@header("{0: <20s} {1: ^10s}".format("task", "ref_count")) 2111def ShowAllRefCounts(cmd_args=None): 2112 """ Prints the ref_count of all tasks 2113 """ 2114 out_str = '' 2115 head_taskp = addressof(kern.globals.tasks) 2116 taskp = Cast(head_taskp.next, 'task *') 2117 print(ShowAllRefCounts.header) 2118 while taskp != head_taskp: 2119 out_str += "{: <#20x}".format(taskp) 2120 out_str += "{: ^10d}\n".format(taskp.ref_count.ref_count) 2121 taskp = Cast(taskp.tasks.next, 'task *') 2122 print(out_str) 2123# EndMacro: showallrefcounts 2124 2125# Macro: showallrunnablethreads 2126@lldb_command('showallrunnablethreads', fancy=True) 2127def ShowAllRunnableThreads(cmd_args=None, cmd_options={}, O=None): 2128 """ Prints the sched usage information for all threads of each task 2129 """ 2130 out_str = '' 2131 for taskp in kern.tasks: 2132 for actp in IterateQueue(taskp.threads, 'thread *', 'task_threads'): 2133 if int(actp.state & 0x4): 2134 ShowActStack([unsigned(actp)], O=O) 2135 2136# EndMacro: showallrunnablethreads 2137 2138# Macro: showallschedusage 2139@lldb_command('showallschedusage') 2140@header("{0:<20s} {1:^10s} {2:^10s} {3:^15s}".format("Thread", "Priority", "State", "sched_usage")) 2141def ShowAllSchedUsage(cmd_args=None): 2142 """ Prints the sched usage information for all threads of each task 2143 """ 2144 out_str = '' 2145 for taskp in kern.tasks: 2146 ShowTask([unsigned(taskp)]) 2147 print(ShowAllSchedUsage.header) 2148 for actp in IterateQueue(taskp.threads, 'thread *', 'task_threads'): 2149 out_str = "{: <#20x}".format(actp) 2150 out_str += "{: ^10s}".format(str(int(actp.sched_pri))) 2151 state = int(actp.state) 2152 thread_state_chars = {0:'', 1:'W', 2:'S', 4:'R', 8:'U', 16:'H', 32:'A', 64:'P', 128:'I'} 2153 state_str = '' 2154 state_str += thread_state_chars[int(state & 0x1)] 2155 state_str += thread_state_chars[int(state & 0x2)] 2156 state_str += thread_state_chars[int(state & 0x4)] 2157 state_str += thread_state_chars[int(state & 0x8)] 2158 state_str += thread_state_chars[int(state & 0x10)] 2159 state_str += thread_state_chars[int(state & 0x20)] 2160 state_str += thread_state_chars[int(state & 0x40)] 2161 state_str += thread_state_chars[int(state & 0x80)] 2162 out_str += "{: ^10s}".format(state_str) 2163 out_str += "{: >15d}".format(actp.sched_usage) 2164 print(out_str + "\n") 2165 print("\n\n") 2166 2167# EndMacro: showallschedusage 2168 2169#Macro: showprocfilessummary 2170@lldb_command('showprocfilessummary') 2171@header("{0: <20s} {1: <20s} {2: >10s}".format("Process", "Name", "Number of Open Files")) 2172def ShowProcFilesSummary(cmd_args=None): 2173 """ Display the summary of open file descriptors for all processes in task list 2174 Usage: showprocfilessummary 2175 """ 2176 print(ShowProcFilesSummary.header) 2177 for proc in kern.procs: 2178 proc_filedesc = addressof(proc.p_fd) 2179 proc_ofiles = proc_filedesc.fd_ofiles 2180 proc_file_count = 0 2181 for fd in range(0, proc_filedesc.fd_afterlast): 2182 if unsigned(proc_ofiles[fd]) != 0: 2183 proc_file_count += 1 2184 print("{0: <#020x} {1: <32s} {2: >10d}".format(proc, GetProcName(proc), proc_file_count)) 2185 2186#EndMacro: showprocfilessummary 2187 2188@lldb_command('workinguserstacks') 2189def WorkingUserStacks(cmd_args=None): 2190 """ Print out the user stack for each thread in a task, followed by the user libraries. 2191 Syntax: (lldb) workinguserstacks <task_t> 2192 """ 2193 if not cmd_args: 2194 print("Insufficient arguments" + ShowTaskUserStacks.__doc__) 2195 return False 2196 task = kern.GetValueFromAddress(cmd_args[0], 'task *') 2197 print(GetTaskSummary.header + " " + GetProcSummary.header) 2198 pval = GetProcFromTask(task) 2199 print(GetTaskSummary(task) + " " + GetProcSummary(pval) + "\n \n") 2200 for thval in IterateQueue(task.threads, 'thread *', 'task_threads'): 2201 print("For thread 0x{0:x}".format(thval)) 2202 try: 2203 ShowThreadUserStack([hex(thval)]) 2204 except Exception as exc_err: 2205 print("Failed to show user stack for thread 0x{0:x}".format(thval)) 2206 if config['debug']: 2207 raise exc_err 2208 else: 2209 print("Enable debugging ('(lldb) xnudebug debug') to see detailed trace.") 2210 WorkingUserLibraries([hex(task)]) 2211 2212@static_var("exec_load_path", 0) 2213@lldb_command("workingkuserlibraries") 2214def WorkingUserLibraries(cmd_args=None): 2215 """ Show binary images known by dyld in target task 2216 For a given user task, inspect the dyld shared library state and print information about all Mach-O images. 2217 Syntax: (lldb)workinguserlibraries <task_t> 2218 """ 2219 if not cmd_args: 2220 print("Insufficient arguments") 2221 print(ShowTaskUserLibraries.__doc__) 2222 return False 2223 2224 print("{0: <18s} {1: <12s} {2: <36s} {3: <50s}".format('address','type','uuid','path')) 2225 out_format = "0x{0:0>16x} {1: <12s} {2: <36s} {3: <50s}" 2226 task = kern.GetValueFromAddress(cmd_args[0], 'task_t') 2227 is_task_64 = int(task.t_flags) & 0x1 2228 dyld_all_image_infos_address = unsigned(task.all_image_info_addr) 2229 cur_data_offset = 0 2230 if dyld_all_image_infos_address == 0: 2231 print("No dyld shared library information available for task") 2232 return False 2233 vers_info_data = GetUserDataAsString(task, dyld_all_image_infos_address, 112) 2234 version = _ExtractDataFromString(vers_info_data, cur_data_offset, "uint32_t") 2235 cur_data_offset += 4 2236 if version > 12: 2237 print("Unknown dyld all_image_infos version number %d" % version) 2238 image_info_count = _ExtractDataFromString(vers_info_data, cur_data_offset, "uint32_t") 2239 WorkingUserLibraries.exec_load_path = 0 2240 if is_task_64: 2241 image_info_size = 24 2242 image_info_array_address = _ExtractDataFromString(vers_info_data, 8, "uint64_t") 2243 dyld_load_address = _ExtractDataFromString(vers_info_data, 8*4, "uint64_t") 2244 dyld_all_image_infos_address_from_struct = _ExtractDataFromString(vers_info_data, 8*13, "uint64_t") 2245 else: 2246 image_info_size = 12 2247 image_info_array_address = _ExtractDataFromString(vers_info_data, 4*2, "uint32_t") 2248 dyld_load_address = _ExtractDataFromString(vers_info_data, 4*5, "uint32_t") 2249 dyld_all_image_infos_address_from_struct = _ExtractDataFromString(vers_info_data, 4*14, "uint32_t") 2250 # Account for ASLR slide before dyld can fix the structure 2251 dyld_load_address = dyld_load_address + (dyld_all_image_infos_address - dyld_all_image_infos_address_from_struct) 2252 2253 i = 0 2254 while i < image_info_count: 2255 image_info_address = image_info_array_address + i * image_info_size 2256 img_data = GetUserDataAsString(task, image_info_address, image_info_size) 2257 if is_task_64: 2258 image_info_addr = _ExtractDataFromString(img_data, 0, "uint64_t") 2259 image_info_path = _ExtractDataFromString(img_data, 8, "uint64_t") 2260 else: 2261 image_info_addr = _ExtractDataFromString(img_data, 0, "uint32_t") 2262 image_info_path = _ExtractDataFromString(img_data, 4, "uint32_t") 2263 PrintImageInfo(task, image_info_addr, image_info_path) 2264 i += 1 2265 2266 # load_path might get set when the main executable is processed. 2267 if WorkingUserLibraries.exec_load_path != 0: 2268 PrintImageInfo(task, dyld_load_address, WorkingUserLibraries.exec_load_path) 2269 return 2270 2271# Macro: showstackaftertask 2272 2273@lldb_command('showstackaftertask', 'F:', fancy=True) 2274def Showstackaftertask(cmd_args=None, cmd_options={}, O=None): 2275 """ Routine to print the thread stacks for all tasks succeeding a given task 2276 Usage: showstackaftertask <0xaddress of task> 2277 or: showstackaftertask -F <taskname> 2278 """ 2279 if "-F" in cmd_options: 2280 # Find the task pointer corresponding to its task name 2281 find_task_str = cmd_options["-F"] 2282 task_list = FindTasksByName(find_task_str) 2283 2284 # Iterate through the list of tasks and print all task stacks thereafter 2285 for tval in task_list: 2286 ListTaskStacks(tval, O=O) 2287 return 2288 2289 if not cmd_args: 2290 raise ArgumentError("Insufficient arguments") 2291 tval = kern.GetValueFromAddress(cmd_args[0], 'task *') 2292 if not tval: 2293 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args))) 2294 else: 2295 ListTaskStacks(tval, O=O) 2296 2297 ZombStacks(O=O) 2298 2299# EndMacro: showstackaftertask 2300 2301def ListTaskStacks(task, O=None): 2302 """ Search for a given task and print the list of all task stacks thereafter. 2303 """ 2304 # Initialize local variable task_flag to mark when a given task is found. 2305 task_flag=0 2306 2307 for t in kern.tasks: 2308 if (task_flag == 1): 2309 ShowTaskStacks(t, O=O) 2310 print("\n") 2311 if (t == task): 2312 task_flag = 1 2313 2314# Macro: showstackafterthread 2315@lldb_command('showstackafterthread', fancy=True) 2316def Showstackafterthread(cmd_args=None, cmd_options={}, O=None): 2317 """ Routine to print the stacks of all threads succeeding a given thread. 2318 Usage: Showstackafterthread <0xaddress of thread> 2319 """ 2320 # local variable thread_flag is used to mark when a given thread is found. 2321 thread_flag=0 2322 if cmd_args: 2323 threadval = kern.GetValueFromAddress(cmd_args[0], 'thread *') 2324 else: 2325 raise ArgumentError("No arguments passed") 2326 # Iterate through list of all tasks to look up a given thread 2327 for t in kern.tasks: 2328 if(thread_flag==1): 2329 pval = GetProcFromTask(t) 2330 print(GetTaskSummary.header + " "+ GetProcSummary.header) 2331 print(GetTaskSummary(t) + " "+ GetProcSummary(pval)) 2332 print("\n") 2333 # Look up for a given thread from the the list of threads of a given task 2334 for thval in IterateQueue(t.threads, 'thread *', 'task_threads'): 2335 if thread_flag == 1: 2336 print("\n") 2337 with O.table(GetThreadSummary.header, indent=True): 2338 print(GetThreadSummary(active_thread, O=O)) 2339 print(GetThreadBackTrace(thval, prefix="\t")+"\n") 2340 print("\n") 2341 2342 if thval == threadval: 2343 pval = GetProcFromTask(t) 2344 process_name = "{:s}".format(GetProcName(pval)) 2345 print("\n\n") 2346 print(" *** Continuing to dump the thread stacks from the process *** :" + " " + process_name) 2347 print("\n\n") 2348 thread_flag = 1 2349 print('\n') 2350 return 2351