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)
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 = ""):
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()
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("<<END") >= 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')
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 <queue_entry *> <struct type> <fieldname>
+ 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 <obj with list_entry *> <struct type> <fieldname>
+ 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 *
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 *