]> git.saurik.com Git - apple/xnu.git/blobdiff - tools/lldbmacros/userspace.py
xnu-4903.241.1.tar.gz
[apple/xnu.git] / tools / lldbmacros / userspace.py
old mode 100644 (file)
new mode 100755 (executable)
index 4b4dd7a..3413fff
@@ -140,7 +140,7 @@ def ShowThreadUserStack(cmd_args=None):
         ShowX86UserStack(thread)
     elif kern.arch == "arm":
         ShowARMUserStack(thread)
-    elif kern.arch == "arm64":
+    elif kern.arch.startswith("arm64"):
         ShowARM64UserStack(thread)
     return True
 
@@ -195,7 +195,6 @@ def PrintUserspaceData(cmd_args=None, cmd_options={}):
 
     return True
 
-
 @lldb_command('showtaskuserargs')
 def ShowTaskUserArgs(cmd_args=None, cmd_options={}):
     """ Read the process argv, env, and apple strings from the user stack
@@ -208,8 +207,9 @@ def ShowTaskUserArgs(cmd_args=None, cmd_options={}):
 
     task = kern.GetValueFromAddress(cmd_args[0], 'task *')
     proc = Cast(task.bsd_info, 'proc *')
+    ptrsize = 8 if int(task.t_flags) & 0x1 else 4
 
-    format_string = "Q" if kern.ptrsize == 8 else "I"
+    format_string = "Q" if ptrsize == 8 else "I"
 
     string_area_size = proc.p_argslen
     string_area_addr = proc.user_stack - string_area_size
@@ -220,7 +220,7 @@ def ShowTaskUserArgs(cmd_args=None, cmd_options={}):
         return False
 
     i = 0
-    pos = string_area_addr - kern.ptrsize
+    pos = string_area_addr - ptrsize
 
     for name in ["apple", "env", "argv"] :
         while True:
@@ -229,9 +229,9 @@ def ShowTaskUserArgs(cmd_args=None, cmd_options={}):
                     break
                 i += 1
 
-            pos -= kern.ptrsize
+            pos -= ptrsize
 
-            user_data_string = GetUserDataAsString(task, pos, kern.ptrsize)
+            user_data_string = GetUserDataAsString(task, pos, ptrsize)
             ptr = struct.unpack(format_string, user_data_string)[0]          
 
             if ptr == 0:
@@ -247,31 +247,17 @@ def ShowTaskUserArgs(cmd_args=None, cmd_options={}):
 
     return True
 
-
-@lldb_command('showtaskuserstacks')
-def ShowTaskUserStacks(cmd_args=None):
-    """ Print out the user stack for each thread in a task, followed by the user libraries.
-        Syntax: (lldb) showtaskuserstacks <task_t>
-        The format is compatible with CrashTracer. You can also use the speedtracer plugin as follows
-        (lldb) showtaskuserstacks <task_t> -p speedtracer
-
-        Note: the address ranges are approximations. Also the list may not be completely accurate. This command expects memory read failures
-        and hence will skip a library if unable to read information. Please use your good judgement and not take the output as accurate
-    """
-    if not cmd_args:
-        raise ArgumentError("Insufficient arguments")
-
-    task = kern.GetValueFromAddress(cmd_args[0], 'task *')
+def ShowTaskUserStacks(task):
     #print GetTaskSummary.header + " " + GetProcSummary.header
     pval = Cast(task.bsd_info, 'proc *')
     #print GetTaskSummary(task) + " " + GetProcSummary(pval) + "\n \n"
     crash_report_format_string = """\
-Process:         {pid: <10d}
+Process:         {pname:s} [{pid:d}]
 Path:            {path: <50s}
 Identifier:      {pname: <30s}
 Version:         ??? (???)
 Code Type:       {parch: <20s}
-Parent Process:  {ppname: >20s}[{ppid:d}]
+Parent Process:  {ppname:s} [{ppid:d}]
 
 Date/Time:       {timest:s}.000 -0800
 OS Version:      {osversion: <20s}
@@ -287,11 +273,14 @@ Synthetic crash log generated from Kernel userstacks
 """
     user_lib_rex = re.compile("([0-9a-fx]+)\s-\s([0-9a-fx]+)\s+(.*?)\s", re.IGNORECASE|re.MULTILINE)
     from datetime import datetime
-    ts = datetime.fromtimestamp(int(pval.p_start.tv_sec))
-    date_string = ts.strftime('%Y-%m-%d %H:%M:%S')
-    is_64 = False
-    if pval.p_flag & 0x4 :
-        is_64 = True
+    if pval:
+        ts = datetime.fromtimestamp(int(pval.p_start.tv_sec))
+        date_string = ts.strftime('%Y-%m-%d %H:%M:%S')
+    else:
+        date_string = "none"
+    is_64 = True
+    if pval and (pval.p_flag & 0x4) == 0 :
+        is_64 = False
 
     parch_s = ""
     if kern.arch == "x86_64" or kern.arch == "i386":
@@ -303,15 +292,25 @@ Synthetic crash log generated from Kernel userstacks
         parch_s = kern.arch
         osversion = "iOS"
     osversion += " ({:s})".format(kern.globals.osversion)
-    print crash_report_format_string.format(pid = pval.p_pid,
-            pname = pval.p_comm,
-            path = pval.p_comm,
-            ppid = pval.p_ppid,
-            ppname = GetProcNameForPid(pval.p_ppid),
+    if pval:
+        pid = pval.p_pid
+        pname = pval.p_comm
+        path = pval.p_comm
+        ppid = pval.p_ppid
+    else:
+        pid = 0
+        pname = "unknown"
+        path = "unknown"
+        ppid = 0
+
+    print crash_report_format_string.format(pid = pid,
+            pname = pname,
+            path = path,
+            ppid = ppid,
+            ppname = GetProcNameForPid(ppid),
             timest = date_string,
             parch = parch_s,
             osversion = osversion
-
         )
     print "Binary Images:"
     ShowTaskUserLibraries([hex(task)])
@@ -327,7 +326,7 @@ Synthetic crash log generated from Kernel userstacks
     printthread_user_stack_ptr = ShowX86UserStack
     if kern.arch == "arm":
         printthread_user_stack_ptr = ShowARMUserStack
-    elif kern.arch =="arm64":
+    elif kern.arch.startswith("arm64"):
         printthread_user_stack_ptr = ShowARM64UserStack
 
     counter = 0
@@ -344,6 +343,36 @@ Synthetic crash log generated from Kernel userstacks
                 print "Enable debugging ('(lldb) xnudebug debug') to see detailed trace."
     return
 
+@lldb_command('showtaskuserstacks', "P:F:")
+def ShowTaskUserStacksCmdHelper(cmd_args=None, cmd_options={}):
+    """ Print out the user stack for each thread in a task, followed by the user libraries.
+        Syntax: (lldb) showtaskuserstacks <task_t>
+            or: (lldb) showtaskuserstacks -P <pid>
+            or: (lldb) showtaskuserstacks -F <task_name>
+        The format is compatible with CrashTracer. You can also use the speedtracer plugin as follows
+        (lldb) showtaskuserstacks <task_t> -p speedtracer
+
+        Note: the address ranges are approximations. Also the list may not be completely accurate. This command expects memory read failures
+        and hence will skip a library if unable to read information. Please use your good judgement and not take the output as accurate
+    """
+    task_list = []
+    if "-F" in cmd_options:
+        task_list = FindTasksByName(cmd_options["-F"])
+    elif "-P" in cmd_options:
+        pidval = ArgumentStringToInt(cmd_options["-P"])
+        for t in kern.tasks:
+            pval = Cast(t.bsd_info, 'proc *')
+            if pval and pval.p_pid == pidval:
+                task_list.append(t)
+                break
+    elif cmd_args:
+        t = kern.GetValueFromAddress(cmd_args[0], 'task *')
+        task_list.append(t)
+    else:
+        raise ArgumentError("Insufficient arguments")
+
+    for task in task_list:
+        ShowTaskUserStacks(task)
 
 def GetUserDataAsString(task, addr, size):
     """ Get data from task's address space as a string of bytes
@@ -367,7 +396,7 @@ def GetUserDataAsString(task, addr, size):
         if not WriteInt64ToMemoryAddress(0, kdp_pmap_addr):
             debuglog("Failed to reset in kdp_pmap from GetUserDataAsString.")
             return ""
-    elif kern.arch in ['arm', 'arm64', 'x86_64'] and long(size) < (2 * kern.globals.page_size):
+    elif (kern.arch == 'x86_64' or kern.arch.startswith('arm')) and (long(size) < (2 * kern.globals.page_size)):
         # Without the benefit of a KDP stub on the target, try to
         # find the user task's physical mapping and memcpy the data.
         # If it straddles a page boundary, copy in two passes
@@ -865,6 +894,9 @@ def SaveKCDataToFile(cmd_args=None, cmd_options={}):
         memory_data = GetUserDataAsString(task, memory_begin_address, memory_size)
     else:
         data_ptr = kern.GetValueFromAddress(memory_begin_address, 'uint8_t *')
+        if data_ptr == 0:
+            print "Kcdata descriptor is NULL"
+            return False
         memory_data = []
         for i in range(memory_size):
             memory_data.append(chr(data_ptr[i]))