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