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