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