+# Macro: showallpte
+@lldb_command('showallpte')
+def ShowAllPte(cmd_args=None):
+ """ Prints out the physical address of the pte for all tasks
+ """
+ head_taskp = addressof(kern.globals.tasks)
+ taskp = Cast(head_taskp.next, 'task *')
+ while taskp != head_taskp:
+ procp = Cast(taskp.bsd_info, 'proc *')
+ out_str = "task = {:#x} pte = {:#x}\t".format(taskp, taskp.map.pmap.ttep)
+ if procp != 0:
+ out_str += "{:s}\n".format(procp.p_comm)
+ else:
+ out_str += "\n"
+ print out_str
+ taskp = Cast(taskp.tasks.next, 'struct task *')
+
+# EndMacro: showallpte
+
+# Macro: showallrefcounts
+@lldb_command('showallrefcounts')
+@header("{0: <20s} {1: ^10s}".format("task", "ref_count"))
+def ShowAllRefCounts(cmd_args=None):
+ """ Prints the ref_count of all tasks
+ """
+ out_str = ''
+ head_taskp = addressof(kern.globals.tasks)
+ taskp = Cast(head_taskp.next, 'task *')
+ print ShowAllRefCounts.header
+ while taskp != head_taskp:
+ out_str += "{: <#20x}".format(taskp)
+ out_str += "{: ^10d}\n".format(taskp.ref_count)
+ taskp = Cast(taskp.tasks.next, 'task *')
+ print out_str
+# EndMacro: showallrefcounts
+
+# Macro: showallrunnablethreads
+@lldb_command('showallrunnablethreads')
+def ShowAllRunnableThreads(cmd_args=None):
+ """ Prints the sched usage information for all threads of each task
+ """
+ out_str = ''
+ for taskp in kern.tasks:
+ for actp in IterateQueue(taskp.threads, 'thread *', 'task_threads'):
+ if int(actp.state & 0x4):
+ ShowActStack([unsigned(actp)])
+
+# EndMacro: showallrunnablethreads
+
+# Macro: showallschedusage
+@lldb_command('showallschedusage')
+@header("{0:<20s} {1:^10s} {2:^10s} {3:^15s}".format("Thread", "Priority", "State", "sched_usage"))
+def ShowAllSchedUsage(cmd_args=None):
+ """ Prints the sched usage information for all threads of each task
+ """
+ out_str = ''
+ for taskp in kern.tasks:
+ ShowTask([unsigned(taskp)])
+ print ShowAllSchedUsage.header
+ for actp in IterateQueue(taskp.threads, 'thread *', 'task_threads'):
+ out_str = "{: <#20x}".format(actp)
+ out_str += "{: ^10s}".format(str(int(actp.sched_pri)))
+ state = int(actp.state)
+ thread_state_chars = {0:'', 1:'W', 2:'S', 4:'R', 8:'U', 16:'H', 32:'A', 64:'P', 128:'I'}
+ state_str = ''
+ state_str += thread_state_chars[int(state & 0x1)]
+ state_str += thread_state_chars[int(state & 0x2)]
+ state_str += thread_state_chars[int(state & 0x4)]
+ state_str += thread_state_chars[int(state & 0x8)]
+ state_str += thread_state_chars[int(state & 0x10)]
+ state_str += thread_state_chars[int(state & 0x20)]
+ state_str += thread_state_chars[int(state & 0x40)]
+ state_str += thread_state_chars[int(state & 0x80)]
+ out_str += "{: ^10s}".format(state_str)
+ out_str += "{: >15d}".format(actp.sched_usage)
+ print out_str + "\n"
+ print "\n\n"
+
+# EndMacro: showallschedusage
+
+#Macro: showprocfilessummary
+@lldb_command('showprocfilessummary')
+@header("{0: <20s} {1: <20s} {2: >10s}".format("Process", "Name", "Number of Open Files"))
+def ShowProcFilesSummary(cmd_args=None):
+ """ Display the summary of open file descriptors for all processes in task list
+ Usage: showprocfilessummary
+ """
+ print ShowProcFilesSummary.header
+ for proc in kern.procs:
+ proc_filedesc = proc.p_fd
+ proc_ofiles = proc_filedesc.fd_ofiles
+ proc_lastfile = unsigned(proc_filedesc.fd_lastfile)
+ count = 0
+ proc_file_count = 0
+ if proc_filedesc.fd_nfiles != 0:
+ while count <= proc_lastfile:
+ if unsigned(proc_ofiles[count]) != 0:
+ proc_file_count += 1
+ count += 1
+ print "{0: <#020x} {1: <20s} {2: >10d}".format(proc, proc.p_comm, proc_file_count)
+
+#EndMacro: showprocfilessummary
+
+@lldb_command('workinguserstacks')
+def WorkingUserStacks(cmd_args=None):
+ """ Print out the user stack for each thread in a task, followed by the user libraries.
+ Syntax: (lldb) workinguserstacks <task_t>
+ """
+ if not cmd_args:
+ print "Insufficient arguments" + ShowTaskUserStacks.__doc__
+ return False
+ task = kern.GetValueFromAddress(cmd_args[0], 'task *')
+ print GetTaskSummary.header + " " + GetProcSummary.header
+ pval = Cast(task.bsd_info, 'proc *')
+ print GetTaskSummary(task) + " " + GetProcSummary(pval) + "\n \n"
+ for thval in IterateQueue(task.threads, 'thread *', 'task_threads'):
+ print "For thread 0x{0:x}".format(thval)
+ try:
+ ShowThreadUserStack([hex(thval)])
+ except Exception as exc_err:
+ print "Failed to show user stack for thread 0x{0:x}".format(thval)
+ if config['debug']:
+ raise exc_err
+ else:
+ print "Enable debugging ('(lldb) xnudebug debug') to see detailed trace."
+ WorkingUserLibraries([hex(task)])
+ return
+
+@static_var("exec_load_path", 0)
+@lldb_command("workingkuserlibraries")
+def WorkingUserLibraries(cmd_args=None):
+ """ Show binary images known by dyld in target task
+ For a given user task, inspect the dyld shared library state and print information about all Mach-O images.
+ Syntax: (lldb)workinguserlibraries <task_t>
+ """
+ if not cmd_args:
+ print "Insufficient arguments"
+ print ShowTaskUserLibraries.__doc__
+ return False
+
+ print "{0: <18s} {1: <12s} {2: <36s} {3: <50s}".format('address','type','uuid','path')
+ out_format = "0x{0:0>16x} {1: <12s} {2: <36s} {3: <50s}"
+ task = kern.GetValueFromAddress(cmd_args[0], 'task_t')
+ is_task_64 = int(task.t_flags) & 0x1
+ dyld_all_image_infos_address = unsigned(task.all_image_info_addr)
+ cur_data_offset = 0
+ if dyld_all_image_infos_address == 0:
+ print "No dyld shared library information available for task"
+ return False
+ vers_info_data = GetUserDataAsString(task, dyld_all_image_infos_address, 112)
+ version = _ExtractDataFromString(vers_info_data, cur_data_offset, "uint32_t")
+ cur_data_offset += 4
+ if version > 12:
+ print "Unknown dyld all_image_infos version number %d" % version
+ image_info_count = _ExtractDataFromString(vers_info_data, cur_data_offset, "uint32_t")
+ WorkingUserLibraries.exec_load_path = 0
+ if is_task_64:
+ image_info_size = 24
+ image_info_array_address = _ExtractDataFromString(vers_info_data, 8, "uint64_t")
+ dyld_load_address = _ExtractDataFromString(vers_info_data, 8*4, "uint64_t")
+ dyld_all_image_infos_address_from_struct = _ExtractDataFromString(vers_info_data, 8*13, "uint64_t")
+ else:
+ image_info_size = 12
+ image_info_array_address = _ExtractDataFromString(vers_info_data, 4*2, "uint32_t")
+ dyld_load_address = _ExtractDataFromString(vers_info_data, 4*5, "uint32_t")
+ dyld_all_image_infos_address_from_struct = _ExtractDataFromString(vers_info_data, 4*14, "uint32_t")
+ # Account for ASLR slide before dyld can fix the structure
+ dyld_load_address = dyld_load_address + (dyld_all_image_infos_address - dyld_all_image_infos_address_from_struct)
+
+ i = 0
+ while i < image_info_count:
+ image_info_address = image_info_array_address + i * image_info_size
+ img_data = GetUserDataAsString(task, image_info_address, image_info_size)
+ if is_task_64:
+ image_info_addr = _ExtractDataFromString(img_data, 0, "uint64_t")
+ image_info_path = _ExtractDataFromString(img_data, 8, "uint64_t")
+ else:
+ image_info_addr = _ExtractDataFromString(img_data, 0, "uint32_t")
+ image_info_path = _ExtractDataFromString(img_data, 4, "uint32_t")
+ PrintImageInfo(task, image_info_addr, image_info_path)
+ i += 1
+
+ # load_path might get set when the main executable is processed.
+ if WorkingUserLibraries.exec_load_path != 0:
+ PrintImageInfo(task, dyld_load_address, WorkingUserLibraries.exec_load_path)
+ return
+
+# Macro: showstackaftertask
+@lldb_command('showstackaftertask','F:')
+def Showstackaftertask(cmd_args=None,cmd_options={}):
+ """ Routine to print the thread stacks for all tasks succeeding a given task
+ Usage: showstackaftertask <0xaddress of task>
+ or: showstackaftertask -F <taskname>
+ """
+ if "-F" in cmd_options:
+ # Find the task pointer corresponding to its task name
+ find_task_str = cmd_options["-F"]
+ task_list = FindTasksByName(find_task_str)
+
+ # Iterate through the list of tasks and print all task stacks thereafter
+ for tval in task_list:
+ ListTaskStacks(tval)
+ return
+
+ if not cmd_args:
+ raise ArgumentError("Insufficient arguments")
+ tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
+ if not tval:
+ raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args)))
+ else:
+ ListTaskStacks(tval)
+
+ ZombStacks()
+ return
+# EndMacro: showstackaftertask
+
+def ListTaskStacks(task):
+ """ Search for a given task and print the list of all task stacks thereafter.
+ """
+ # Initialize local variable task_flag to mark when a given task is found.
+ task_flag=0
+
+ for t in kern.tasks:
+ if (task_flag == 1):
+ ShowTaskStacks(t)
+ print "\n"
+ if (t == task):
+ task_flag = 1
+
+# Macro: showstackafterthread
+@lldb_command('showstackafterthread')
+def Showstackafterthread(cmd_args = None):
+ """ Routine to print the stacks of all threads succeeding a given thread.
+ Usage: Showstackafterthread <0xaddress of thread>
+ """
+ # local variable thread_flag is used to mark when a given thread is found.
+ thread_flag=0
+ if cmd_args:
+ threadval = kern.GetValueFromAddress(cmd_args[0], 'thread *')
+ else:
+ raise ArgumentError("No arguments passed")
+ # Iterate through list of all tasks to look up a given thread
+ for t in kern.tasks:
+ if(thread_flag==1):
+ pval = Cast(t.bsd_info, 'proc *')
+ print GetTaskSummary.header + " "+ GetProcSummary.header
+ print GetTaskSummary(t) + " "+ GetProcSummary(pval)
+ print "\n"
+ # Look up for a given thread from the the list of threads of a given task
+ for thval in IterateQueue(t.threads, 'thread *', 'task_threads'):
+ if (thread_flag==1):
+ print "\n"
+ print " " + GetThreadSummary.header
+ print " " + GetThreadSummary(thval)
+ print GetThreadBackTrace(thval, prefix="\t")+"\n"
+ print "\n"
+
+ if(thval==threadval):
+ pval = Cast(t.bsd_info, 'proc *')
+ process_name = "{:s}".format(pval.p_comm)
+ print "\n\n"
+ print " *** Continuing to dump the thread stacks from the process *** :" + " " + process_name
+ print "\n\n"
+ thread_flag = 1
+ print '\n'
+ return