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