]> git.saurik.com Git - apple/xnu.git/blob - tools/lldbmacros/process.py
xnu-2422.115.4.tar.gz
[apple/xnu.git] / tools / lldbmacros / process.py
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
6 from xnu import *
7 import sys, shlex
8 from utils import *
9 from core.lazytarget import *
10 import xnudefines
11
12 def 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
50 def 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
62 def 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')
80 def 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')
90 def 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')
99 def 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"))
110 def 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'))
134 def 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"))
213 def 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:')
280 def 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')
307 def 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')
328 def 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')
349 def 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')
369 def 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')
424 def 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')
494 def 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')
514 def 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')
530 def 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
549 def 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
561 def 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:')
582 def 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')
608 def 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:")
617 def 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')
641 def 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')
654 def 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')
669 def 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')
691 def 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')
703 def 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')
725 def 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
742 def 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')
770 def 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')
782 def 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')
793 def 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')
803 def 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
828 def 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')
843 def 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
864 def 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
873 def 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
905 def 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')
937 def 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
1043 def 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
1094 def 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"))
1113 def 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:')
1140 def 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')
1165 def 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"))
1179 def 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')
1192 def 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')
1209 def 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