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