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 xnudefines 11 12def GetProcInfo(proc): 13 """ returns a string name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields. 14 params: 15 proc : value object representing a proc in the kernel 16 returns: 17 str : A string describing various information for process. 18 """ 19 out_string = "" 20 out_string += ("Process {p: <#020x}\n\tname {p.p_comm: <20s}\n\tpid:{p.p_pid: <6d} " + 21 "task:{p.task: <#020x} p_stat:{p.p_stat: <6d} parent pid: {p.p_ppid: <6d}\n" 22 ).format(p=proc) 23 #print the Creds 24 ucred = proc.p_ucred 25 if ucred: 26 out_string += "Cred: euid {:d} ruid {:d} svuid {:d}\n".format(ucred.cr_posix.cr_uid, 27 ucred.cr_posix.cr_ruid, 28 ucred.cr_posix.cr_svuid ) 29 #print the flags 30 flags = int(proc.p_flag) 31 out_string += "Flags: {0: <#020x}\n".format(flags) 32 i = 1 33 num = 1 34 while num <= flags: 35 if flags & num: 36 out_string += "\t" + xnudefines.proc_flag_explain_strings[i] + "\n" 37 elif num == 0x4: #special case for 32bit flag 38 out_string += "\t" + xnudefines.proc_flag_explain_strings[0] + "\n" 39 i += 1 40 num = num << 1 41 out_string += "State: " 42 state_val = proc.p_stat 43 if state_val < 1 or state_val > len(xnudefines.proc_state_strings) : 44 out_string += "(Unknown)" 45 else: 46 out_string += xnudefines.proc_state_strings[int(state_val)] 47 48 return out_string 49 50def GetProcNameForPid(pid): 51 """ Finds the name of the process corresponding to a given pid 52 params: 53 pid : int, pid you want to find the procname for 54 returns 55 str : Name of the process corresponding to the pid, "Unknown" if not found 56 """ 57 for p in kern.procs: 58 if int(p.p_pid) == int(pid): 59 return str(p.p_comm) 60 return "Unknown" 61 62def GetProcForPid(search_pid): 63 """ Finds the value object representing a proc in the kernel based on its pid 64 params: 65 search_pid : int, pid whose proc structure you want to find 66 returns: 67 value : The value object representing the proc, if a proc corresponding 68 to the given pid is found. Returns None otherwise 69 """ 70 if search_pid == 0: 71 return kern.globals.initproc 72 else: 73 headp = kern.globals.allproc 74 for proc in IterateListEntry(headp, 'struct proc *', 'p_list'): 75 if proc.p_pid == search_pid: 76 return proc 77 return None 78 79@lldb_command('allproc') 80def AllProc(cmd_args=None): 81 """ Walk through the allproc structure and print procinfo for each process structure. 82 params: 83 cmd_args - [] : array of strings passed from lldb command prompt 84 """ 85 for proc in kern.procs : 86 print GetProcInfo(proc) 87 88 89@lldb_command('zombproc') 90def ZombProc(cmd_args=None): 91 """ Routine to print out all procs in the zombie list 92 params: 93 cmd_args - [] : array of strings passed from lldb command prompt 94 """ 95 for proc in kern.zombprocs: 96 print GetProcInfo(proc) 97 98@lldb_command('zombstacks') 99def ZombStacks(cmd_args=None): 100 """ Routine to print out all stacks of tasks that are exiting 101 """ 102 for proc in kern.zombprocs: 103 if proc.p_stat != 5: 104 t = Cast(proc.task, 'task *') 105 ShowTaskStacks(t) 106#End of Zombstacks 107 108@lldb_type_summary(['task', 'task_t']) 109@header("{0: <20s} {1: <20s} {2: <20s} {3: >5s} {4: <5s}".format("task","vm_map", "ipc_space", "#acts", "flags")) 110def GetTaskSummary(task): 111 """ Summarizes the important fields in task structure. 112 params: task: value - value object representing a task in kernel 113 returns: str - summary of the task 114 """ 115 out_string = "" 116 format_string = '{0: <#020x} {1: <#020x} {2: <#020x} {3: >5d} {4: <5s}' 117 thread_count = int(task.thread_count) 118 task_flags = '' 119 if hasattr(task, "suppression_generation") and (int(task.suppression_generation) & 0x1) == 0x1: 120 task_flags += 'P' 121 if hasattr(task, "suspend_count") and int(task.suspend_count) > 0: 122 task_flags += 'S' 123 if hasattr(task, "imp_receiver") and int(task.imp_receiver) == 1: 124 task_flags += 'R' 125 if hasattr(task, "imp_donor") and int(task.imp_donor) == 1: 126 task_flags += 'D' 127 if hasattr(task, "task_imp_assertcnt") and int(task.task_imp_assertcnt) > 0: 128 task_flags += 'B' 129 out_string += format_string.format(task, task.map, task.itk_space, thread_count, task_flags) 130 return out_string 131 132@lldb_type_summary(['thread *', 'thread_t']) 133@header("{0: <24s} {1: <10s} {2: <20s} {3: <6s} {4: <10s} {5: <5s} {6: <20s} {7: <45s} {8: <20s} {9: <20s}".format('thread', 'thread_id', 'processor', 'pri', 'io_policy', 'state', 'wait_queue', 'wait_event', 'wmesg', 'thread_name')) 134def GetThreadSummary(thread): 135 """ Summarize the thread structure. It decodes the wait state and waitevents from the data in the struct. 136 params: thread: value - value objecte representing a thread in kernel 137 returns: str - summary of a thread 138 """ 139 out_string = "" 140 format_string = "{0: <24s} {1: <10s} {2: <20s} {3: <6s} {4: <10s} {5: <5s} {6: <20s} {7: <45s} {8: <20s} {9: <20s}" 141 thread_ptr_str = str("{0: <#020x}".format(thread)) 142 if int(thread.static_param) : 143 thread_ptr_str+="[WQ]" 144 thread_id = hex(thread.thread_id) 145 thread_name = '' 146 processor = hex(thread.last_processor) 147 sched_priority = str(int(thread.sched_pri)) 148 149 io_policy_str = "" 150 if int(thread.uthread) != 0: 151 uthread = Cast(thread.uthread, 'uthread *') 152 #check for thread name 153 if int(uthread.pth_name) != 0 : 154 th_name_strval = Cast(uthread.pth_name, 'char *') 155 if len(str(th_name_strval)) > 0 : 156 thread_name = str(th_name_strval) 157 158 #check for io_policy flags 159 if int(uthread.uu_flag) & 0x400: 160 io_policy_str+='RAGE ' 161 162 #now flags for task_policy 163 164 io_policy_str = "" 165 166 if int(thread.effective_policy.darwinbg) != 0: 167 io_policy_str += "B" 168 if int(thread.effective_policy.lowpri_cpu) != 0: 169 io_policy_str += "L" 170 171 if int(thread.effective_policy.io_tier) != 0: 172 io_policy_str += "T" 173 if int(thread.effective_policy.io_passive) != 0: 174 io_policy_str += "P" 175 if int(thread.effective_policy.terminated) != 0: 176 io_policy_str += "D" 177 178 state = int(thread.state) 179 thread_state_chars = {0:'', 1:'W', 2:'S', 4:'R', 8:'U', 16:'H', 32:'A', 64:'P', 128:'I'} 180 state_str = '' 181 state_str += thread_state_chars[int(state & 0x1)] 182 state_str += thread_state_chars[int(state & 0x2)] 183 state_str += thread_state_chars[int(state & 0x4)] 184 state_str += thread_state_chars[int(state & 0x8)] 185 state_str += thread_state_chars[int(state & 0x10)] 186 state_str += thread_state_chars[int(state & 0x20)] 187 state_str += thread_state_chars[int(state & 0x40)] 188 state_str += thread_state_chars[int(state & 0x80)] 189 190 #wait queue information 191 wait_queue_str = '' 192 wait_event_str = '' 193 wait_message = '' 194 if ( state & 0x1 ) != 0: 195 #we need to look at the waitqueue as well 196 wait_queue_str = str("{0: <#020x}".format(int(hex(thread.wait_queue), 16))) 197 wait_event_str = str("{0: <#020x}".format(int(hex(thread.wait_event), 16))) 198 wait_event_str_sym = kern.Symbolicate(int(hex(thread.wait_event), 16)) 199 if len(wait_event_str_sym) > 0: 200 wait_event_str = wait_event_str.strip() + " <" + wait_event_str_sym + ">" 201 if int(thread.uthread) != 0 : 202 uthread = Cast(thread.uthread, 'uthread *') 203 if int(uthread.uu_wmesg) != 0: 204 wait_message = str(Cast(uthread.uu_wmesg, 'char *')) 205 206 out_string += format_string.format(thread_ptr_str, thread_id, processor, sched_priority, io_policy_str, state_str, wait_queue_str, wait_event_str, wait_message, thread_name ) 207 return out_string 208 209 210 211@lldb_type_summary(['proc']) 212@header("{0: >6s} {1: ^20s} {2: >14s} {3: ^10s} {4: <20s}".format("pid", "process", "io_policy", "wq_state", "command")) 213def GetProcSummary(proc): 214 """ Summarize the process data. 215 params: 216 proc : value - value representaitng a proc * in kernel 217 returns: 218 str - string summary of the process. 219 """ 220 out_string = "" 221 format_string= "{0: >6d} {1: >#020x} {2: >14s} {3: >2d} {4: >2d} {5: >2d} {6: <20s}" 222 pval = proc.GetSBValue() 223 #code.interact(local=locals()) 224 if str(pval.GetType()) != str(gettype('proc *')) : 225 return "Unknown type " + str(pval.GetType()) + " " + str(hex(proc)) 226 if not proc: 227 out_string += "Process " + hex(proc) + " is not valid." 228 return out_string 229 pid = int(proc.p_pid) 230 proc_addr = int(hex(proc), 16) 231 proc_rage_str = "" 232 if int(proc.p_lflag) & 0x400000 : 233 proc_rage_str = "RAGE" 234 235 task = Cast(proc.task, 'task *') 236 237 io_policy_str = "" 238 239 if int(task.effective_policy.darwinbg) != 0: 240 io_policy_str += "B" 241 if int(task.effective_policy.lowpri_cpu) != 0: 242 io_policy_str += "L" 243 244 if int(task.effective_policy.io_tier) != 0: 245 io_policy_str += "T" 246 if int(task.effective_policy.io_passive) != 0: 247 io_policy_str += "P" 248 if int(task.effective_policy.terminated) != 0: 249 io_policy_str += "D" 250 251 if int(task.effective_policy.t_suspended) != 0: 252 io_policy_str += "S" 253 if int(task.effective_policy.t_latency_qos) != 0: 254 io_policy_str += "Q" 255 if int(task.effective_policy.t_sup_active) != 0: 256 io_policy_str += "A" 257 258 259 try: 260 work_queue = Cast(proc.p_wqptr, 'workqueue *') 261 if proc.p_wqptr != 0 : 262 wq_num_threads = int(work_queue.wq_nthreads) 263 wq_idle_threads = int(work_queue.wq_thidlecount) 264 wq_req_threads = int(work_queue.wq_reqcount) 265 else: 266 wq_num_threads = 0 267 wq_idle_threads = 0 268 wq_req_threads = 0 269 except: 270 wq_num_threads = -1 271 wq_idle_threads = -1 272 wq_req_threads = -1 273 process_name = str(proc.p_comm) 274 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) 275 return out_string 276 277# Macro: showtask 278 279@lldb_command('showtask', 'F:') 280def ShowTask(cmd_args=None, cmd_options={}): 281 """ Routine to print a summary listing of given task 282 Usage: showtask <address of task> 283 or : showtask -F <name of task> 284 """ 285 task_list = [] 286 if "-F" in cmd_options: 287 task_list = FindTasksByName(cmd_options['-F']) 288 else: 289 if not cmd_args: 290 raise ArgumentError("Invalid arguments passed.") 291 292 tval = kern.GetValueFromAddress(cmd_args[0], 'task *') 293 if not tval: 294 raise ("Unknown arguments: %r" % cmd_args) 295 task_list.append(tval) 296 297 for tval in task_list: 298 print GetTaskSummary.header + " " + GetProcSummary.header 299 pval = Cast(tval.bsd_info, 'proc *') 300 print GetTaskSummary(tval) +" "+ GetProcSummary(pval) 301 302# EndMacro: showtask 303 304# Macro: showpid 305 306@lldb_command('showpid') 307def ShowPid(cmd_args=None): 308 """ Routine to print a summary listing of task corresponding to given pid 309 Usage: showpid <pid value> 310 """ 311 if not cmd_args: 312 print "No arguments passed" 313 print ShowPid.__doc__ 314 return False 315 pidval = ArgumentStringToInt(cmd_args[0]) 316 for t in kern.tasks: 317 pval = Cast(t.bsd_info, 'proc *') 318 if pval and pval.p_pid == pidval: 319 print GetTaskSummary.header + " " + GetProcSummary.header 320 print GetTaskSummary(t) + " " + GetProcSummary(pval) 321 break 322 323# EndMacro: showpid 324 325# Macro: showproc 326 327@lldb_command('showproc') 328def ShowProc(cmd_args=None): 329 """ Routine to print a summary listing of task corresponding to given proc 330 Usage: showproc <address of proc> 331 """ 332 if not cmd_args: 333 print "No arguments passed" 334 print ShowProc.__doc__ 335 return False 336 pval = kern.GetValueFromAddress(cmd_args[0], 'proc *') 337 if not pval: 338 print "unknown arguments:", str(cmd_args) 339 return False 340 print GetTaskSummary.header + " " + GetProcSummary.header 341 tval = Cast(pval.task, 'task *') 342 print GetTaskSummary(tval) +" "+ GetProcSummary(pval) 343 344# EndMacro: showproc 345 346# Macro: showprocinfo 347 348@lldb_command('showprocinfo') 349def ShowProcInfo(cmd_args=None): 350 """ Routine to display name, pid, parent & task for the given proc address 351 It also shows the Cred, Flags and state of the process 352 Usage: showprocinfo <address of proc> 353 """ 354 if not cmd_args: 355 print "No arguments passed" 356 print ShowProcInfo.__doc__ 357 return False 358 pval = kern.GetValueFromAddress(cmd_args[0], 'proc *') 359 if not pval: 360 print "unknown arguments:", str(cmd_args) 361 return False 362 print GetProcInfo(pval) 363 364# EndMacro: showprocinfo 365 366#Macro: showprocfiles 367 368@lldb_command('showprocfiles') 369def ShowProcFiles(cmd_args=None): 370 """ Given a proc_t pointer, display the list of open file descriptors for the referenced process. 371 Usage: showprocfiles <proc_t> 372 """ 373 if not cmd_args: 374 print ShowProcFiles.__doc__ 375 return 376 proc = kern.GetValueFromAddress(cmd_args[0], 'proc_t') 377 proc_filedesc = proc.p_fd 378 proc_lastfile = unsigned(proc_filedesc.fd_lastfile) 379 proc_ofiles = proc_filedesc.fd_ofiles 380 if unsigned(proc_ofiles) == 0: 381 print 'No open files for proc {0: <s}'.format(cmd_args[0]) 382 return 383 print "{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO') 384 print "{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("") 385 count = 0 386 387 # Filetype map 388 filetype_dict = { 389 1: 'VNODE', 390 2: 'SOCKET', 391 3: 'PSXSHM', 392 4: 'PSXSEM', 393 5: 'KQUEUE', 394 6: 'PIPE', 395 7: 'FSEVENTS' 396 } 397 398 while count <= proc_lastfile: 399 if unsigned(proc_ofiles[count]) != 0: 400 out_str = '' 401 proc_fd_flags = proc_ofiles[count].f_flags 402 proc_fd_fglob = proc_ofiles[count].f_fglob 403 out_str += "{0: <5d} ".format(count) 404 out_str += "{0: <#18x} ".format(unsigned(proc_fd_fglob)) 405 out_str += "0x{0:0>8x} ".format(unsigned(proc_fd_flags)) 406 proc_fd_ftype = unsigned(proc_fd_fglob.fg_ops.fo_type) 407 if proc_fd_ftype in filetype_dict: 408 out_str += "{0: <8s} ".format(filetype_dict[proc_fd_ftype]) 409 else: 410 out_str += "?: {0: <5d} ".format(proc_fd_ftype) 411 out_str += "{0: <#18x} ".format(unsigned(proc_fd_fglob.fg_data)) 412 if proc_fd_ftype == 1: 413 fd_name = Cast(proc_fd_fglob.fg_data, 'struct vnode *').v_name 414 out_str += "{0: <64s}".format(fd_name) 415 out_str += "\n" 416 print out_str 417 count += 1 418 419#EndMacro: showprocfiles 420 421#Macro: showtty 422 423@lldb_command('showtty') 424def ShowTTY(cmd_args=None): 425 """ Display information about a struct tty 426 Usage: showtty <tty struct> 427 """ 428 if not cmd_args: 429 print ShowTTY.__doc__ 430 return 431 432 tty = kern.GetValueFromAddress(cmd_args[0], 'struct tty *') 433 print "TTY structure at: {0: <s}".format(cmd_args[0]) 434 print "Last input to raw queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty.t_rawq.c_cs), tty.t_rawq.c_cs) 435 print "Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty.t_canq.c_cs), tty.t_canq.c_cs) 436 print "Last output data: {0: <#18x} \"{1: <s}\"".format(unsigned(tty.t_outq.c_cs), tty.t_outq.c_cs) 437 tty_state_info = [ 438 ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'], 439 ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'], 440 ['', 'TS_BUSY (Draining output)'], 441 ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'], 442 ['', 'TS_FLUSH (Outq has been flushed during DMA)'], 443 ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'], 444 ['', 'TS_TBLOCK (Further input blocked)'], 445 ['', 'TS_TIMEOUT (Wait for output char processing)'], 446 ['', 'TS_TTSTOP (Output paused)'], 447 ['', 'TS_WOPEN (Open in progress)'], 448 ['', 'TS_XCLUDE (Tty requires exclusivity)'], 449 ['', 'TS_BKSL (State for lowercase \\ work)'], 450 ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'], 451 ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'], 452 ['', 'TS_LNCH (Next character is literal)'], 453 ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'], 454 ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'], 455 ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'], 456 ['', 'TS_SNOOP (Device is being snooped on)'], 457 ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'], 458 ['', 'TS_ZOMBIE (Connection lost)'], 459 ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'], 460 ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'], 461 ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)'] 462 ] 463 index = 0 464 mask = 0x1 465 tty_state = unsigned(tty.t_state) 466 print "State:" 467 while index < 24: 468 if tty_state & mask != 0: 469 if len(tty_state_info[index][1]) > 0: 470 print '\t' + tty_state_info[index][1] 471 else: 472 if len(tty_state_info[index][0]) > 0: 473 print '\t' + tty_state_info[index][0] 474 index += 1 475 mask = mask << 1 476 print "Flags: 0x{0:0>8x}".format(unsigned(tty.t_flags)) 477 print "Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty.t_pgrp)) 478 print "Enclosing session: 0x{0:0>16x}".format(unsigned(tty.t_session)) 479 print "Termios:" 480 print "\tInput Flags: 0x{0:0>8x}".format(unsigned(tty.t_termios.c_iflag)) 481 print "\tOutput Flags: 0x{0:0>8x}".format(unsigned(tty.t_termios.c_oflag)) 482 print "\tControl Flags: 0x{0:0>8x}".format(unsigned(tty.t_termios.c_cflag)) 483 print "\tLocal Flags: 0x{0:0>8x}".format(unsigned(tty.t_termios.c_lflag)) 484 print "\tInput Speed: {0: <8d}".format(tty.t_termios.c_ispeed) 485 print "\tOutput Speed: {0: <8d}".format(tty.t_termios.c_ospeed) 486 print "High Watermark: {0: <d} bytes".format(tty.t_hiwat) 487 print "Low Watermark : {0: <d} bytes".format(tty.t_lowat) 488 489#EndMacro: showtty 490 491#Macro: dumpcallqueue 492 493@lldb_command('dumpcallqueue') 494def DumpCallQueue(cmd_args=None): 495 """ Displays the contents of the specified call_entry queue. 496 Usage: dumpcallqueue <queue_head_t *> 497 """ 498 if not cmd_args: 499 print DumpCallQueue.__doc__ 500 return 501 print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC') 502 callhead = kern.GetValueFromAddress(cmd_args[0], 'queue_head_t *') 503 count = 0 504 for callentry in IterateQueue(callhead, 'struct call_entry *', 'q_link'): 505 print "{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format( 506 unsigned(callentry), unsigned(callentry.param0), unsigned(callentry.param1), 507 unsigned(callentry.deadline), unsigned(callentry.func)) 508 count += 1 509 print "{0: <d} entries!".format(count) 510 511#EndMacro: dumpcallqueue 512 513@lldb_command('showalltasks') 514def ShowAllTasks(cmd_args=None): 515 """ Routine to print a summary listing of all the tasks 516 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items" 517 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung 518 io_policy -> RAGE - rapid aging of vnodes requested 519 NORM - normal I/O explicitly requested (this is the default) 520 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions) 521 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes) 522 """ 523 global kern 524 print GetTaskSummary.header + " " + GetProcSummary.header 525 for t in kern.tasks: 526 pval = Cast(t.bsd_info, 'proc *') 527 print GetTaskSummary(t) +" "+ GetProcSummary(pval) 528 529@lldb_command('showterminatedtasks') 530def ShowTerminatedTasks(cmd_args=None): 531 """ Routine to print a summary listing of all the terminated tasks 532 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items" 533 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung 534 io_policy -> RAGE - rapid aging of vnodes requested 535 NORM - normal I/O explicitly requested (this is the default) 536 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions) 537 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes) 538 syntax: (lldb)showallterminatedtasks 539 """ 540 global kern 541 print GetTaskSummary.header + " " + GetProcSummary.header 542 for t in kern.terminated_tasks: 543 pval = Cast(t.bsd_info, 'proc *') 544 print GetTaskSummary(t) +" "+ GetProcSummary(pval) 545 return True 546 547# Macro: showtaskstacks 548 549def ShowTaskStacks(task): 550 """ Print a task with summary and stack information for each of its threads 551 """ 552 global kern 553 print GetTaskSummary.header + " " + GetProcSummary.header 554 pval = Cast(task.bsd_info, 'proc *') 555 print GetTaskSummary(task) + " " + GetProcSummary(pval) 556 for th in IterateQueue(task.threads, 'thread *', 'task_threads'): 557 print " " + GetThreadSummary.header 558 print " " + GetThreadSummary(th) 559 print GetThreadBackTrace(th, prefix=" ") + "\n" 560 561def FindTasksByName(searchstr, ignore_case=True): 562 """ Search the list of tasks by name. 563 params: 564 searchstr: str - a regex like string to search for task 565 ignore_case: bool - If False then exact matching will be enforced 566 returns: 567 [] - array of task object. Empty if not found any 568 """ 569 re_options = 0 570 if ignore_case: 571 re_options = re.IGNORECASE 572 search_regex = re.compile(searchstr, re_options) 573 retval = [] 574 for t in kern.tasks: 575 pval = Cast(t.bsd_info, "proc *") 576 process_name = "{:s}".format(pval.p_comm) 577 if search_regex.search(process_name): 578 retval.append(t) 579 return retval 580 581@lldb_command('showtaskstacks', 'F:') 582def ShowTaskStacksCmdHelper(cmd_args=None, cmd_options={}): 583 """ Routine to print out the stack for each thread in a task 584 Usage: showtaskstacks <0xaddress of task> 585 or: showtaskstacks -F launchd 586 """ 587 588 if "-F" in cmd_options: 589 find_task_str = cmd_options["-F"] 590 task_list = FindTasksByName(find_task_str) 591 for tval in task_list: 592 ShowTaskStacks(tval) 593 return 594 595 if not cmd_args: 596 raise ArgumentError("No arguments passed") 597 598 tval = kern.GetValueFromAddress(cmd_args[0], 'task *') 599 if not tval: 600 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args))) 601 else: 602 ShowTaskStacks(tval) 603 return 604 605# EndMacro: showtaskstacks 606 607@lldb_command('showallthreads') 608def ShowAllThreads(cmd_args = None): 609 """ Display info about all threads in the system 610 """ 611 for t in kern.tasks: 612 ShowTaskThreads([str(int(t))]) 613 print " \n" 614 return 615 616@lldb_command('showtaskthreads', "F:") 617def ShowTaskThreads(cmd_args = None, cmd_options={}): 618 """ Display thread information for a given task 619 Usage: showtaskthreads <0xaddress of task> 620 or: showtaskthreads -F <name> 621 """ 622 task_list = [] 623 if "-F" in cmd_options: 624 task_list = FindTasksByName(cmd_options["-F"]) 625 elif cmd_args: 626 t = kern.GetValueFromAddress(cmd_args[0], 'task *') 627 task_list.append(t) 628 else: 629 raise ArgumentError("No arguments passed") 630 631 for task in task_list: 632 print GetTaskSummary.header + " " + GetProcSummary.header 633 pval = Cast(task.bsd_info, 'proc *') 634 print GetTaskSummary(task) + " " + GetProcSummary(pval) 635 print "\t" + GetThreadSummary.header 636 for thval in IterateQueue(task.threads, 'thread *', 'task_threads'): 637 print "\t" + GetThreadSummary(thval) 638 return 639 640@lldb_command('showact') 641def ShowAct(cmd_args=None): 642 """ Routine to print out the state of a specific thread. 643 usage: showact <activation> 644 """ 645 if cmd_args == None or len(cmd_args) < 1: 646 print "No arguments passed" 647 print ShowAct.__doc__ 648 return False 649 threadval = kern.GetValueFromAddress(cmd_args[0], 'thread *') 650 print GetThreadSummary.header 651 print GetThreadSummary(threadval) 652 653@lldb_command('showactstack') 654def ShowActStack(cmd_args=None): 655 """ Routine to print out the stack of a specific thread. 656 usage: showactstack <activation> 657 """ 658 if cmd_args == None or len(cmd_args) < 1: 659 print "No arguments passed" 660 print ShowAct.__doc__.strip() 661 return False 662 threadval = kern.GetValueFromAddress(cmd_args[0], 'thread *') 663 print GetThreadSummary.header 664 print GetThreadSummary(threadval) 665 print GetThreadBackTrace(threadval, prefix="\t") 666 return 667 668@lldb_command('switchtoact') 669def SwitchToAct(cmd_args=None): 670 """ Switch to different context specified by activation 671 This command allows gdb to examine the execution context and call 672 stack for the specified activation. For example, to view the backtrace 673 for an activation issue "switchtoact <address>", followed by "bt". 674 Before resuming execution, issue a "resetctx" command, to 675 return to the original execution context. 676 """ 677 if cmd_args == None or len(cmd_args) < 1: 678 print "No arguments passed" 679 print SwitchToAct.__doc__.strip() 680 return False 681 thval = kern.GetValueFromAddress(cmd_args[0], 'thread *') 682 lldbthread = GetLLDBThreadForKernelThread(thval) 683 print GetThreadSummary.header 684 print GetThreadSummary(thval) 685 LazyTarget.GetProcess().selected_thread = lldbthread 686 if not LazyTarget.GetProcess().SetSelectedThread(lldbthread): 687 print "Failed to switch thread." 688 return 689# Macro: showallstacks 690@lldb_command('showallstacks') 691def ShowAllStacks(cmd_args=None): 692 """Routine to print out the stack for each thread in the system. 693 """ 694 for t in kern.tasks: 695 ShowTaskStacks(t) 696 print " \n" 697 return 698 699# EndMacro: showallstacks 700 701# Macro: showcurrentstacks 702@lldb_command('showcurrentstacks') 703def ShowCurrentStacks(cmd_args=None): 704 """ Routine to print out the thread running on each cpu (incl. its stack) 705 """ 706 processor_list = kern.GetGlobalVariable('processor_list') 707 current_processor = processor_list 708 while unsigned(current_processor) > 0: 709 print "\nProcessor {: <#020x} State {: <d} (cpu_id {: >#04x})".format(current_processor, int(current_processor.state), int(current_processor.cpu_id)) 710 active_thread = current_processor.active_thread 711 if unsigned(active_thread) != 0 : 712 task_val = active_thread.task 713 proc_val = Cast(task_val.bsd_info, 'proc *') 714 print GetTaskSummary.header + " " + GetProcSummary.header 715 print GetTaskSummary(task_val) + " " + GetProcSummary(proc_val) 716 print "\t" + GetThreadSummary.header 717 print "\t" + GetThreadSummary(active_thread) 718 print "\tBacktrace:" 719 print GetThreadBackTrace(active_thread, prefix="\t") 720 current_processor = current_processor.processor_list 721 return 722# EndMacro: showcurrentstacks 723 724@lldb_command('showcurrentthreads') 725def ShowCurrentThreads(cmd_args=None): 726 """ Display info about threads running on each cpu """ 727 processor_list = kern.GetGlobalVariable('processor_list') 728 current_processor = processor_list 729 while unsigned(current_processor) > 0: 730 print "Processor {: <#020x} State {: <d} (cpu_id {: >#04x})".format(current_processor, int(current_processor.state), int(current_processor.cpu_id)) 731 active_thread = current_processor.active_thread 732 if unsigned(active_thread) != 0 : 733 task_val = active_thread.task 734 proc_val = Cast(task_val.bsd_info, 'proc *') 735 print GetTaskSummary.header + " " + GetProcSummary.header 736 print GetTaskSummary(task_val) + " " + GetProcSummary(proc_val) 737 print "\t" + GetThreadSummary.header 738 print "\t" + GetThreadSummary(active_thread) 739 current_processor = current_processor.processor_list 740 return 741 742def GetFullBackTrace(frame_addr, verbosity = vHUMAN, prefix = ""): 743 """ Get backtrace across interrupt context. 744 params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7) 745 prefix - str - prefix for each line of output. 746 747 """ 748 out_string = "" 749 bt_count = 0 750 frame_ptr = frame_addr 751 previous_frame_ptr = 0 752 # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header 753 mh_execute_addr = int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16) 754 while frame_ptr and frame_ptr != previous_frame_ptr and bt_count < 128: 755 if (kern.arch != 'arm' and frame_ptr < mh_execute_addr) or (kern.arch == 'arm' and frame_ptr > mh_execute_addr): 756 break 757 pc_val = kern.GetValueFromAddress(frame_ptr + kern.ptrsize,'uintptr_t *') 758 pc_val = unsigned(dereference(pc_val)) 759 out_string += prefix + GetSourceInformationForAddress(pc_val) + "\n" 760 bt_count +=1 761 previous_frame_ptr = frame_ptr 762 frame_val = kern.GetValueFromAddress((frame_ptr), 'uintptr_t *') 763 if unsigned(frame_val) == 0: 764 break 765 frame_ptr = unsigned(dereference(frame_val)) 766 767 return out_string 768 769@lldb_command('fullbt') 770def FullBackTrace(cmd_args=[]): 771 """ Show full backtrace across the interrupt boundary. 772 Syntax: fullbt <frame ptr> 773 Example: kfullbt `$rbp` 774 """ 775 if len(cmd_args) < 1: 776 print FullBackTrace.__doc__ 777 return False 778 print GetFullBackTrace(ArgumentStringToInt(cmd_args[0]), prefix="\t") 779 780 781@lldb_command('symbolicate') 782def SymbolicateAddress(cmd_args=[]): 783 """ Symbolicate an address for symbol information from loaded symbols 784 Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr" 785 """ 786 if len(cmd_args) < 1: 787 print "Invalid address.\nSyntax: symbolicate <address>" 788 return False 789 print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args[0])) 790 return True 791 792@lldb_command('showinitchild') 793def ShowInitChild(cmd_args=None): 794 """ Routine to print out all processes in the system 795 which are children of init process 796 """ 797 headp = kern.globals.initproc.p_children 798 for pp in IterateListEntry(headp, 'struct proc *', 'p_sibling'): 799 print GetProcInfo(pp) 800 return 801 802@lldb_command('showproctree') 803def ShowProcTree(cmd_args=None): 804 """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes. 805 If no argument is given, showproctree will print all the processes in the system. 806 If pid is specified, showproctree prints all the descendants of the indicated process 807 """ 808 search_pid = 0 809 if cmd_args: 810 search_pid = ArgumentStringToInt(cmd_args[0]) 811 812 if search_pid < 0: 813 print "pid specified must be a positive number" 814 print ShowProcTree.__doc__ 815 return 816 817 hdr_format = "{0: <6s} {1: <14s} {2: <9s}\n" 818 out_string = hdr_format.format("PID", "PROCESS", "POINTER") 819 out_string += hdr_format.format('='*3, '='*7, '='*7) 820 proc = GetProcForPid(search_pid) 821 out_string += "{0: <6d} {1: <14s} [ {2: #019x} ]\n".format(proc.p_ppid, proc.p_pptr.p_comm, unsigned(proc.p_pptr)) 822 out_string += "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(proc.p_pid, proc.p_comm, unsigned(proc)) 823 print out_string 824 ShowProcTreeRecurse(proc, "| ") 825 826 return 827 828def ShowProcTreeRecurse(proc, prefix=""): 829 """ Prints descendants of a given proc in hierarchial tree form 830 params: 831 proc : core.value representing a struct proc * in the kernel 832 returns: 833 str : String containing info about a given proc and its descendants in tree form 834 """ 835 if proc.p_childrencnt > 0: 836 head_ptr = proc.p_children.lh_first 837 838 for p in IterateListEntry(proc.p_children, 'struct proc *', 'p_sibling'): 839 print prefix + "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(p.p_pid, p.p_comm, unsigned(p)) 840 ShowProcTreeRecurse(p, prefix + "| ") 841 842@lldb_command('showthreadfortid') 843def ShowThreadForTid(cmd_args=None): 844 """ The thread structure contains a unique thread_id value for each thread. 845 This command is used to retrieve the address of the thread structure(thread_t) 846 corresponding to a given thread_id. 847 """ 848 if not cmd_args: 849 print "Please provide thread_t whose tid you'd like to look up" 850 print ShowThreadForTid.__doc__ 851 return 852 search_tid = ArgumentStringToInt(cmd_args[0]) 853 for taskp in kern.tasks: 854 for actp in IterateQueue(taskp.threads, 'struct thread *', 'task_threads'): 855 if search_tid == int(actp.thread_id): 856 print "Found {0: #019x}".format(actp) 857 print GetThreadSummary.header 858 print GetThreadSummary(actp) 859 return 860 print "Not a valid thread_id" 861 862# Macro: showallprocessors 863 864def GetProcessorSummary(processor): 865 """ Internal function to print summary of processor 866 params: processor - value representing struct processor * 867 return: str - representing the details of given processor 868 """ 869 out_str = "Processor {: <#012x} ".format(processor) 870 out_str += "State {:d} (cpu_id {:#x})\n".format(processor.state, processor.cpu_id) 871 return out_str 872 873def GetRunQSummary(runq): 874 """ Internal function to print summary of run_queue 875 params: runq - value representing struct run_queue * 876 return: str - representing the details of given run_queue 877 """ 878 out_str = " Priority Run Queue Info: Count {: <10d}\n".format(runq.count) 879 runq_queue_i = 0 880 runq_queue_count = sizeof(runq.queues)/sizeof(runq.queues[0]) 881 while runq.count and (runq_queue_i < runq_queue_count): 882 runq_queue_head = addressof(runq.queues[runq_queue_i]) 883 runq_queue_p = runq_queue_head.next 884 if unsigned(runq_queue_p) != unsigned(runq_queue_head): 885 runq_queue_this_count = 0 886 while runq_queue_p != runq_queue_head: 887 runq_queue_this_count = runq_queue_this_count + 1 888 runq_queue_p_thread = Cast(runq_queue_p, 'thread_t') 889 # Get the task information 890 out_str += GetTaskSummary.header + " " + GetProcSummary.header 891 pval = Cast(runq_queue_p_thread.task.bsd_info, 'proc *') 892 out_str += GetTaskSummary(runq_queue_p_thread.task) +" "+ GetProcSummary(pval) 893 # Get the thread information with related stack traces 894 out_str += GetThreadSummary.header + GetThreadSummary(runq_queue_p_thread) 895 out_str += GetThreadBackTrace(LazyTarget.GetProcess().GetThreadByID(int(runq_queue_p_thread.thread_id)), 896 prefix="\t") 897 runq_queue_p = runq_queue_p.next 898 899 out_str += " Queue Priority {: <3d} [{: <#012x}] Count {:d}\n".format(runq_queue_i, 900 runq_queue_head, runq_queue_this_count) 901 902 runq_queue_i = runq_queue_i + 1 903 return out_str 904 905def GetGrrrSummary(grrr_runq): 906 """ Internal function to print summary of grrr_run_queue 907 params: grrr_runq - value representing struct grrr_run_queue * 908 return: str - representing the details of given grrr_run_queue 909 """ 910 out_str = " GRRR Info: Count {: <10d} Weight {: <10d} Current Group {: <#012x}\n".format(grrr_runq.count, 911 grrr_runq.weight, grrr_runq.current_group) 912 grrr_group_i = 0 913 grrr_group_count = sizeof(grrr_runq.groups)/sizeof(grrr_runq.groups[0]) 914 while grrr_runq.count and (grrr_group_i < grrr_group_count): 915 grrr_group = addressof(grrr_runq.groups[grrr_group_i]) 916 runq_queue_p = runq_queue_head.next 917 if grrr_group.count > 0: 918 out_str += " Group {: <3d} [{: <#012x}] ".format(grrr_group.index, grrr_group) 919 out_str += "Count {:d} Weight {:d}\n".format(grrr_group.count, grrr_group.weight) 920 grrr_group_client_head = addressof(grrr_group.clients) 921 grrr_group_client = grrr_group_client_head.next 922 while grrr_group_client != grrr_group_client_head: 923 grrr_group_client_thread = Cast(grrr_group_client, 'thread_t') 924 # Get the task information 925 out_str += GetTaskSummary.header + " " + GetProcSummary.header 926 pval = Cast(grrr_group_client_thread.task.bsd_info, 'proc *') 927 out_str += GetTaskSummary(grrr_group_client_thread.task) +" "+ GetProcSummary(pval) 928 # Get the thread information with related stack traces 929 out_str += GetThreadSummary.header + GetThreadSummary(grrr_group_client_thread) 930 out_str += GetThreadBackTrace(LazyTarget.GetProcess().GetThreadByID(int(grrr_group_client_thread.thread_id)), 931 prefix="\t") 932 grrr_group_client = grrr_group_client.next 933 grrr_group_i = grrr_group_i + 1 934 return out_str 935 936@lldb_command('showallprocessors') 937def ShowAllProcessors(cmd_args=None): 938 """ Routine to print information of all psets and processors 939 Usage: showallprocessors 940 """ 941 pset = addressof(kern.globals.pset0) 942 show_grrr = 0 943 show_priority_runq = 0 944 show_priority_pset_runq = 0 945 show_fairshare_grrr = 0 946 show_fairshare_list = 0 947 sched_enum_val = kern.globals._sched_enum 948 949 if sched_enum_val == 1: 950 show_priority_runq = 1 951 show_fairshare_list = 1 952 elif sched_enum_val == 2: 953 show_priority_pset_runq = 1 954 show_fairshare_list = 1 955 elif sched_enum_val == 4: 956 show_grrr = 1 957 show_fairshare_grrr = 1 958 elif sched_enum_val == 5: 959 show_priority_runq = 1 960 show_fairshare_list = 1 961 elif sched_enum_val == 6: 962 show_priority_pset_runq = 1 963 show_fairshare_list = 1 964 965 out_str = '' 966 while pset: 967 out_str += "Processor Set {: <#012x} Count {:d} (cpu_id {:<#x}-{:<#x})\n".format(pset, 968 pset.cpu_set_count, pset.cpu_set_low, pset.cpu_set_hi) 969 out_str += " Active Processors:\n" 970 active_queue_head = addressof(pset.active_queue) 971 active_elt = active_queue_head.next 972 while active_elt != active_queue_head: 973 processor = Cast(active_elt, 'processor *') 974 out_str += " " 975 out_str += GetProcessorSummary(processor) 976 if show_priority_runq: 977 runq = addressof(processor.runq) 978 out_str += GetRunQSummary(runq) 979 if show_grrr: 980 grrr_runq = addressof(processor.grrr_runq) 981 out_str += GetGrrrSummary(grrr_runq) 982 983 if processor.processor_meta and (processor.processor_meta.primary == 984 processor): 985 processor_meta_idle_head = addressof(processor.processor_meta.idle_queue) 986 processor_meta_idle = processor_meta_idle_head.next 987 while processor_meta_idle != processor_meta_idle_head: 988 out_str += " Idle Meta Processor: " 989 out_str += GetProcessorSummary(processor_meta_idle) 990 processor_meta_idle = processor_meta_idle.next 991 active_elt = active_elt.next 992 993 out_str += " Idle Processors:\n" 994 idle_queue_head = addressof(pset.idle_queue) 995 idle_elt = idle_queue_head.next 996 while idle_elt != idle_queue_head: 997 processor = Cast(idle_elt, 'processor *') 998 out_str += " " 999 out_str += GetProcessorSummary(processor) 1000 1001 if processor.processor_meta and (processor.processor_meta.primary == 1002 processor): 1003 processor_meta_idle_head = addressof(processor.processor_meta.idle_queue) 1004 processor_meta_idle = processor_meta_idle_head.next 1005 while processor_meta_idle != processor_meta_idle_head: 1006 out_str += " Idle Meta Processor: " 1007 out_str += GetProcessorSummary(processor_meta_idle) 1008 processor_meta_idle = processor_meta_idle.next 1009 idle_elt = idle_elt.next 1010 1011 if show_priority_pset_runq: 1012 runq = addressof(pset.pset_runq) 1013 out_str += "\n" + GetRunQSummary(runq) 1014 pset = pset.pset_list 1015 1016 out_str += "\nRealtime Queue Count {:d}\n".format(kern.globals.rt_runq.count) 1017 rt_runq_head = addressof(kern.globals.rt_runq.queue) 1018 rt_runq_local = rt_runq_head.next 1019 while rt_runq_local != rt_runq_head: 1020 rt_runq_thread = Cast(rt_runq_local, 'thread *') 1021 out_str += ShowTask([unsigned(rt_runq_thread.task)]) 1022 out_str += ShowAct([unsigned(rt_runq_thread)]) 1023 rt_runq_local = rt_runq_local.next 1024 1025 out_str += "\n" 1026 if show_fairshare_list: 1027 out_str += "Fair Share Queue Count {:d}\n".format(kern.globals.fs_runq.count) 1028 fs_runq_head = addressof(kern.globals.fs_runq.queue) 1029 fs_runq_local = fs_runq_head.next 1030 while fs_runq_local != fs_runq_head: 1031 fs_runq_thread = Cast(fs_runq, 'thread *') 1032 out_str += ShowTask([unsigned(fs_runq_thread.task)]) 1033 out_str += ShowAct([unsigned(rt_runq_thread)]) 1034 fs_runq_local = fs_runq_local.next 1035 if show_fairshare_grrr: 1036 out_str += "Fair Share Queue Count {:d}\n".format(kern.globals.fs_grrr_runq.count) 1037 fs_grrr = addressof(kern.globals.fs_grrr_runq) 1038 out_str += GetGrrrSummary(fs_grrr) 1039 1040 print out_str 1041# EndMacro: showallprocessors 1042 1043def GetLedgerEntrySummary(ledger_template, ledger, i): 1044 """ Internal function to get internals of a ledger entry (*not* a ledger itself) 1045 params: ledger_template - value representing struct ledger_template_t for the task or thread 1046 ledger - value representing struct ledger_entry * 1047 return: str - formatted output information of ledger entries 1048 """ 1049 ledger_limit_infinity = (uint64_t(0x1).value << 63) - 1 1050 lf_refill_scheduled = 0x0400 1051 lf_tracking_max = 0x4000 1052 1053 out_str = '' 1054 now = kern.globals.sched_tick / 20 1055 lim_pct = 0 1056 1057 out_str += "{: >25s} {:<d}:".format(ledger_template.lt_entries[i].et_key, i) 1058 out_str += "{: >13d} ".format(ledger.le_credit - ledger.le_debit) 1059 if (ledger.le_flags & lf_tracking_max): 1060 out_str += "{:9d} {:5d} ".format(ledger._le.le_peaks[0].le_max, now - ledger._le.le_peaks[0].le_time) 1061 out_str += "{:9d} {:4d} ".format(ledger._le.le_peaks[1].le_max, now - ledger._le.le_peaks[1].le_time) 1062 else: 1063 out_str += " - - - - " 1064 1065 out_str += "{:12d} {:12d} ".format(ledger.le_credit, ledger.le_debit) 1066 if (unsigned(ledger.le_limit) != ledger_limit_infinity): 1067 out_str += "{:12d} ".format(unsigned(ledger.le_limit)) 1068 else: 1069 out_str += " - " 1070 1071 if (ledger.le_flags & lf_refill_scheduled): 1072 out_str += "{:15d} ".format(ledger._le.le_refill.le_refill_period) 1073 else: 1074 out_str += " - " 1075 1076 if (ledger.le_flags & lf_refill_scheduled): 1077 out_str += "{:9d} ".format((unsigned(ledger.le_limit) * 100) / ledger._le.le_refill.le_refill_period) 1078 else: 1079 out_str += " - " 1080 1081 if (unsigned(ledger.le_warn_level) != ledger_limit_infinity): 1082 out_str += "{:9d} ".format((unsigned(ledger.le_warn_level) * 100) / unsigned(ledger.le_limit)) 1083 else: 1084 out_str += " - " 1085 1086 if ((ledger.le_credit - ledger.le_debit) > unsigned(ledger.le_limit)): 1087 out_str += " X " 1088 else: 1089 out_str += " " 1090 1091 out_str += "{:#8x}\n".format(ledger.le_flags) 1092 return out_str 1093 1094def GetThreadLedgerSummary(thread_val): 1095 """ Internal function to get a summary of ledger entries for the given thread 1096 params: thread - value representing struct thread * 1097 return: str - formatted output information for ledger entries of the input thread 1098 """ 1099 out_str = " [{:#08x}]\n".format(thread_val) 1100 ledgerp = thread_val.t_threadledger 1101 if ledgerp: 1102 i = 0 1103 while i != ledgerp.l_template.lt_cnt: 1104 out_str += GetLedgerEntrySummary(kern.globals.thread_ledger_template, 1105 ledgerp.l_entries[i], i) 1106 i = i + 1 1107 return out_str 1108 1109@header("{0: <15s} {1: >9s} {2: <2s} {3: >12s} {4: >9s} {5: >6s} {6: >8s} {7: <10s} {8: <9s} \ 1110 {9: <12s} {10: <7s} {11: <15s} {12: <8s} {13: <9s} {14: <6s} {15: >6s}".format( 1111 "task [thread]", "entry", "#", "balance", "peakA", "(age)", "peakB", "(age)", "credit", 1112 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags")) 1113def GetTaskLedgers(task_val): 1114 """ Internal function to get summary of ledger entries from the task and its threads 1115 params: task_val - value representing struct task * 1116 return: str - formatted output information for ledger entries of the input task 1117 """ 1118 out_str = '' 1119 task_ledgerp = task_val.ledger 1120 i = 0 1121 out_str += "{: #08x} ".format(task_val) 1122 pval = Cast(task_val.bsd_info, 'proc *') 1123 if pval: 1124 out_str += "{: <5s}:\n".format(pval.p_comm) 1125 else: 1126 out_str += "Invalid process:\n" 1127 while i != task_ledgerp.l_template.lt_cnt: 1128 out_str += GetLedgerEntrySummary(kern.globals.task_ledger_template, task_ledgerp.l_entries[i], i) 1129 i = i + 1 1130 1131 # Now walk threads 1132 for thval in IterateQueue(task_val.threads, 'thread *', 'task_threads'): 1133 out_str += GetThreadLedgerSummary(thval) 1134 1135 return out_str 1136 1137# Macro: showtaskledgers 1138 1139@lldb_command('showtaskledgers', 'F:') 1140def ShowTaskLedgers(cmd_args=None, cmd_options={}): 1141 """ Routine to print a summary of ledger entries for the task and all of its threads 1142 Usage: showtaskledgers <address of task> 1143 or : showtaskledgers -F <name of task> 1144 """ 1145 if "-F" in cmd_options: 1146 task_list = FindTasksByName(cmd_options["-F"]) 1147 for tval in task_list: 1148 print GetTaskLedgers.header 1149 print GetTaskLedgers(tval) 1150 return 1151 1152 if not cmd_args: 1153 raise ArgumentError("No arguments passed.") 1154 tval = kern.GetValueFromAddress(cmd_args[0], 'task *') 1155 if not tval: 1156 raise ArgumentError("unknown arguments: %r" %cmd_args) 1157 print GetTaskLedgers.header 1158 print GetTaskLedgers(tval) 1159 1160# EndMacro: showtaskledgers 1161 1162# Macro: showalltaskledgers 1163 1164@lldb_command('showalltaskledgers') 1165def ShowAllTaskLedgers(cmd_args=None): 1166 """ Routine to print a summary of ledger entries for all tasks and respective threads 1167 Usage: showalltaskledgers 1168 """ 1169 for t in kern.tasks: 1170 task_val = unsigned(t) 1171 ShowTaskLedgers([task_val]) 1172 1173# EndMacro: showalltaskledgers 1174 1175# Macro: showprocuuidpolicytable 1176 1177@lldb_type_summary(['proc_uuid_policy_entry']) 1178@header("{0: <36s} {1: <10s}".format("uuid", "flags")) 1179def GetProcUUIDPolicyEntrySummary(entry): 1180 """ Summarizes the important fields in proc_uuid_policy_entry structure. 1181 params: entry: value - value object representing an entry 1182 returns: str - summary of the entry 1183 """ 1184 data = [] 1185 for i in range(16): 1186 data.append(int(entry.uuid[i])) 1187 flags = unsigned(entry.flags) 1188 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) 1189 return out_string 1190 1191@lldb_command('showprocuuidpolicytable') 1192def ShowProcUUIDPolicyTable(cmd_args=None): 1193 """ Routine to print the proc UUID policy table 1194 Usage: showprocuuidpolicytable 1195 """ 1196 hashslots = unsigned(kern.globals.proc_uuid_policy_hash_mask) 1197 print "{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary.header 1198 for i in range(0, hashslots+1): 1199 headp = addressof(kern.globals.proc_uuid_policy_hashtbl[i]) 1200 entrynum = 0 1201 for entry in IterateListEntry(headp, 'struct proc_uuid_policy_entry *', 'entries'): 1202 print "{0: >2d}.{1: <5d} ".format(i, entrynum) + GetProcUUIDPolicyEntrySummary(entry) 1203 entrynum += 1 1204 1205 1206# EndMacro: showprocuuidpolicytable 1207 1208@lldb_command('showalltaskpolicy') 1209def ShowAllTaskPolicy(cmd_args=None): 1210 """ 1211 Routine to print a summary listing of all the tasks 1212 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items" 1213 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung 1214 io_policy -> RAGE - rapid aging of vnodes requested 1215 NORM - normal I/O explicitly requested (this is the default) 1216 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions) 1217 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes) 1218 """ 1219 global kern 1220 print GetTaskSummary.header + " " + GetProcSummary.header 1221 for t in kern.tasks: 1222 pval = Cast(t.bsd_info, 'proc *') 1223 print GetTaskSummary(t) +" "+ GetProcSummary(pval) 1224 requested_strings = [ 1225 ["int_darwinbg", "DBG-int"], 1226 ["ext_darwinbg", "DBG-ext"], 1227 ["int_iotier", "iotier-int"], 1228 ["ext_iotier", "iotier-ext"], 1229 ["int_iopassive", "passive-int"], 1230 ["ext_iopassive", "passive-ext"], 1231 ["bg_iotier", "bg-iotier"], 1232 ["terminated", "terminated"], 1233 ["th_pidbind_bg", "bg-pidbind"], 1234 ["th_workq_bg", "bg-workq"], 1235 ["t_apptype", "apptype"], 1236 ["t_boosted", "boosted"], 1237 ["t_int_gpu_deny", "gpudeny-int"], 1238 ["t_ext_gpu_deny", "gpudeny-ext"], 1239 ["t_role", "role"], 1240 ["t_visibility", "vis"], 1241 ["t_tal_enabled", "tal-enabled"], 1242 ["t_base_latency_qos", "latency-base"], 1243 ["t_over_latency_qos", "latency-override"], 1244 ["t_base_through_qos", "throughput-base"], 1245 ["t_over_through_qos", "throughput-override"] 1246 ] 1247 1248 requested="" 1249 for value in requested_strings: 1250 if t.requested_policy.__getattr__(value[0]) : 1251 requested+=value[1] + ": " + str(t.requested_policy.__getattr__(value[0])) + " " 1252 else: 1253 requested+="" 1254 1255 suppression_strings = [ 1256 ["t_sup_active", "active"], 1257 ["t_sup_lowpri_cpu", "lowpri-cpu"], 1258 ["t_sup_timer", "timer-throttling"], 1259 ["t_sup_disk", "disk-throttling"], 1260 ["t_sup_cpu_limit", "cpu-limits"], 1261 ["t_sup_suspend", "suspend"] 1262 ] 1263 1264 suppression="" 1265 for value in suppression_strings: 1266 if t.requested_policy.__getattr__(value[0]) : 1267 suppression+=value[1] + ": " + str(t.requested_policy.__getattr__(value[0])) + " " 1268 else: 1269 suppression+="" 1270 1271 effective_strings = [ 1272 ["darwinbg", "background"], 1273 ["lowpri_cpu", "lowpri-cpu"], 1274 ["io_tier", "iotier"], 1275 ["io_passive", "passive"], 1276 ["all_sockets_bg", "bg-allsockets"], 1277 ["new_sockets_bg", "bg-newsockets"], 1278 ["bg_iotier", "bg-iotier"], 1279 ["terminated", "terminated"], 1280 ["t_gpu_deny", "gpu-deny"], 1281 ["t_tal_engaged", "tal-engaged"], 1282 ["t_suspended", "suspended"], 1283 ["t_watchers_bg", "bg-watchers"], 1284 ["t_latency_qos", "latency-qos"], 1285 ["t_through_qos", "throughput-qos"], 1286 ["t_sup_active", "suppression-active"], 1287 ["t_role", "role"], 1288 ["t_visibility", "vis"] 1289 ] 1290 1291 effective="" 1292 for value in effective_strings: 1293 if t.effective_policy.__getattr__(value[0]) : 1294 effective+=value[1] + ": " + str(t.effective_policy.__getattr__(value[0])) + " " 1295 else: 1296 effective+="" 1297 1298 1299 pended_strings = [ 1300 ["t_updating_policy", "updating"], 1301 ["update_sockets", "update_sockets"], 1302 ["t_update_timers", "update_timers"], 1303 ["t_update_watchers", "update_watchers"] 1304 ] 1305 1306 pended="" 1307 for value in pended_strings: 1308 if t.pended_policy.__getattr__(value[0]) : 1309 pended+=value[1] + ": " + str(t.pended_policy.__getattr__(value[0])) + " " 1310 else: 1311 pended+="" 1312 1313 print "requested: " + requested 1314 print "suppression: " + suppression 1315 print "effective: " + effective 1316 print "pended: " + pended 1317 1318 1319 1320 1321