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