X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/39236c6e673c41db228275375ab7fdb0f837b292..ecc0ceb4089d506a0b8d16686a95817b331af9cb:/tools/lldbmacros/xnu.py diff --git a/tools/lldbmacros/xnu.py b/tools/lldbmacros/xnu.py index d72c3aeef..bc3830f7c 100644 --- a/tools/lldbmacros/xnu.py +++ b/tools/lldbmacros/xnu.py @@ -99,7 +99,7 @@ def lldb_command(cmd_name, option_string = ''): try: stream.setOptions(command_args, option_string) if stream.verbose_level != 0: - config['verbosity'] = stream.verbose_level + config['verbosity'] += stream.verbose_level with RedirectStdStreams(stdout=stream) : if option_string: obj(cmd_args=stream.target_cmd_args, cmd_options=stream.target_cmd_options) @@ -285,8 +285,8 @@ def GetLLDBThreadForKernelThread(thread_obj): sbthread = lldb_process.GetThreadByID(tid) if not sbthread.IsValid(): - raise RuntimeError("Unable to find lldb thread for tid={0:d} thread = {1:#018x}".format(tid, thread_obj)) - + raise RuntimeError("Unable to find lldb thread for tid={0:d} thread = {1:#018x} (#16049947: have you put 'settings set target.load-script-from-symbol-file true' in your .lldbinit?)".format(tid, thread_obj)) + return sbthread def GetThreadBackTrace(thread_obj, verbosity = vHUMAN, prefix = ""): @@ -321,18 +321,32 @@ def GetThreadBackTrace(thread_obj, verbosity = vHUMAN, prefix = ""): if iteration == 0 and not is_continuation: out_string += prefix +"stacktop = {:#018x}\n".format(frame_p) - + if not function: # No debug info for 'function'. - symbol = frame.GetSymbol() - file_addr = addr.GetFileAddress() - start_addr = symbol.GetStartAddress().GetFileAddress() - symbol_name = symbol.GetName() - symbol_offset = file_addr - start_addr out_string += prefix if not is_continuation: out_string += "{fp:#018x} ".format(fp = frame_p) - out_string += "{addr:#018x} {mod}`{symbol} + {offset} \n".format(addr=load_addr, mod=mod_name, symbol=symbol_name, offset=symbol_offset) + + symbol = frame.GetSymbol() + if not symbol: + symbol_name = "None" + symbol_offset = load_addr + kmod_val = kern.globals.kmod + for kval in IterateLinkedList(kmod_val, 'next'): + if load_addr >= unsigned(kval.address) and \ + load_addr <= (unsigned(kval.address) + unsigned(kval.size)): + symbol_name = kval.name + symbol_offset = load_addr - unsigned(kval.address) + break + out_string += "{:#018x} {:s} + {:#x} \n".format(load_addr, symbol_name, symbol_offset) + else: + file_addr = addr.GetFileAddress() + start_addr = symbol.GetStartAddress().GetFileAddress() + symbol_name = symbol.GetName() + symbol_offset = file_addr - start_addr + out_string += "{addr:#018x} {mod}`{symbol} + {offset:#x} \n".format(addr=load_addr, + mod=mod_name, symbol=symbol_name, offset=symbol_offset) else: # Debug info is available for 'function'. func_name = frame.GetFunctionName() @@ -518,32 +532,74 @@ def ShowVersion(cmd_args=None): print kern.version -@lldb_command('paniclog') -def ShowPanicLog(cmd_args=None): +@lldb_command('paniclog', 'S') +def ShowPanicLog(cmd_args=None, cmd_options={}): """ Display the paniclog information + usage: (lldb) paniclog + options: + -v : increase verbosity + -S : parse stackshot data (if panic stackshot available) """ - panic_buf = kern.globals.debug_buf - panic_buf_start = addressof(panic_buf) + binary_data_bytes_to_skip = 0 + if hasattr(kern.globals, "kc_panic_data"): + binary_data_bytes_to_skip = unsigned(kern.globals.kc_panic_data.kcd_addr_end) - unsigned(kern.globals.kc_panic_data.kcd_addr_begin) + if binary_data_bytes_to_skip > 0: + binary_data_bytes_to_skip += sizeof("struct kcdata_item") + else: + binary_data_bytes_to_skip = 0 + + if "-S" in cmd_options: + if hasattr(kern.globals, "kc_panic_data"): + kc_data = unsigned(addressof(kern.globals.kc_panic_data)) + ts = int(time.time()) + ss_binfile = "/tmp/panic_%d.bin" % ts + ss_ipsfile = "/tmp/stacks_%d.ips" % ts + print "savekcdata 0x%x -O %s" % (kc_data, ss_binfile) + SaveKCDataToFile(["0x%x" % kc_data], {"-O":ss_binfile}) + self_path = str(__file__) + base_dir_name = self_path[:self_path.rfind("/")] + print "python %s/kcdata.py %s -s %s" % (base_dir_name, ss_binfile, ss_ipsfile) + (c,so,se) = RunShellCommand("python %s/kcdata.py %s -s %s" % (base_dir_name, ss_binfile, ss_ipsfile)) + if c == 0: + print "Saved ips stackshot file as %s" % ss_ipsfile + else: + print "Failed to run command: exit code: %d, SO: %s SE: %s" % (c, so, se) + else: + print "kc_panic_data is unavailable for this kernel config." + + panic_buf = kern.globals.debug_buf_addr + panic_buf_start = unsigned(panic_buf) panic_buf_end = unsigned(kern.globals.debug_buf_ptr) num_bytes = panic_buf_end - panic_buf_start if num_bytes == 0 : return - panic_data = panic_buf.GetSBValue().GetData() - err = lldb.SBError() - line = '' - for i in range(0, num_bytes): - c = panic_data.GetUnsignedInt8(err, i) - if chr(c) == '\n': - if line =='': - line = " " - print line - line = '' - else: - line += chr(c) - - if len(line) > 0: - print line - + out_str = "" + warn_str = "" + num_print_bytes = 0 + in_binary_data_region = False + pos = 0 + while pos < num_bytes: + p_char = str(panic_buf[pos]) + out_str += p_char + if p_char == '\n': + if not in_binary_data_region: + num_print_bytes += 1 + print out_str + if (out_str.find("Data: BEGIN>>") >= 0): + in_binary_data_region = True + pos += binary_data_bytes_to_skip - 1 + if (out_str.find("<= 0): + in_binary_data_region = False + out_str = "" + if num_print_bytes > 4096 and config['verbosity'] == vHUMAN: + warn_str = "LLDBMacro Warning: The paniclog is too large. Trimming to 4096 bytes." + warn_str += " If you wish to see entire log please use '-v' argument." + break + pos += 1 + + if warn_str: + print warn_str + return @lldb_command('showbootargs') @@ -611,6 +667,74 @@ def ShowLLDBTypeSummaries(cmd_args=[]): lldb_run_command("type category "+ action +" kernel") print "Successfully "+action+"d the kernel type summaries. %s" % trailer_msg +@lldb_command('walkqueue_head', 'S') +def WalkQueueHead(cmd_args=[], cmd_options={}): + """ walk a queue_head_t and list all members in it. Note this is for queue_head_t. refer to osfmk/kern/queue.h + Option: -S - suppress summary output. + Usage: (lldb) walkqueue_head + ex: (lldb) walkqueue_head 0x7fffff80 "thread *" "task_threads" + + """ + global lldb_summary_definitions + if not cmd_args: + raise ArgumentError("invalid arguments") + if len(cmd_args) != 3: + raise ArgumentError("insufficient arguments") + queue_head = kern.GetValueFromAddress(cmd_args[0], 'struct queue_entry *') + el_type = cmd_args[1] + field_name = cmd_args[2] + showsummary = False + if el_type in lldb_summary_definitions: + showsummary = True + if '-S' in cmd_options: + showsummary = False + + for i in IterateQueue(queue_head, el_type, field_name): + if showsummary: + print lldb_summary_definitions[el_type](i) + else: + print "{0: <#020x}".format(i) + + + +@lldb_command('walklist_entry', 'S') +def WalkList(cmd_args=[], cmd_options={}): + """ iterate over a list as defined with LIST_ENTRY in bsd/sys/queue.h + params: + object addr - value : address of object + element_type - str : Type of the next element + field_name - str : Name of the field in next element's structure + + Option: -S - suppress summary output. + Usage: (lldb) walklist_entry + ex: (lldb) walklist_entry 0x7fffff80 "struct proc *" "p_sibling" + + """ + global lldb_summary_definitions + if not cmd_args: + raise ArgumentError("invalid arguments") + if len(cmd_args) != 3: + raise ArgumentError("insufficient arguments") + el_type = cmd_args[1] + queue_head = kern.GetValueFromAddress(cmd_args[0], el_type) + field_name = cmd_args[2] + + showsummary = False + if el_type in lldb_summary_definitions: + showsummary = True + if '-S' in cmd_options: + showsummary = False + elt = queue_head + while unsigned(elt) != 0: + i = elt + elt = elt.__getattr__(field_name).le_next + if showsummary: + print lldb_summary_definitions[el_type](i) + else: + print "{0: <#020x}".format(i) + + + from memory import * from process import * from ipc import * @@ -624,3 +748,10 @@ from pci import * from misc import * from apic import * from scheduler import * +from atm import * +from structanalyze import * +from ipcimportancedetail import * +from bank import * +from kauth import * +from waitq import * +from usertaskgdbserver import *