X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/3e170ce000f1506b7b5d2c5c7faec85ceabb573d..b226f5e54a60dc81db17b1260381d7dbfea3cdf1:/tools/lldbmacros/userspace.py diff --git a/tools/lldbmacros/userspace.py b/tools/lldbmacros/userspace.py old mode 100644 new mode 100755 index 4b4dd7ae5..3413fff96 --- a/tools/lldbmacros/userspace.py +++ b/tools/lldbmacros/userspace.py @@ -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 - The format is compatible with CrashTracer. You can also use the speedtracer plugin as follows - (lldb) showtaskuserstacks -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 + or: (lldb) showtaskuserstacks -P + or: (lldb) showtaskuserstacks -F + The format is compatible with CrashTracer. You can also use the speedtracer plugin as follows + (lldb) showtaskuserstacks -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]))