1""" 2 XNU Triage commands 3""" 4from xnu import * 5import sys, shlex 6from utils import * 7import xnudefines 8import re 9import os.path 10 11# Macro: xi 12def OutputAddress(cmd_args=None): 13 """ Returns out address and symbol corresponding to it without newline 14 Parameters: <address whose symbol is needed> 15 """ 16 if not cmd_args: 17 print("No arguments passed") 18 print(OutputAddress.__doc__) 19 return False 20 a = unsigned(cmd_args[0]) 21 cmd_str = "image lookup -a {:#x}".format(a) 22 cmd_out = lldb_run_command(cmd_str) 23 if len(cmd_out) != 0 and cmd_out != "ERROR:": 24 cmd_out1 = cmd_out.split('\n') 25 if len(cmd_out1) != 0: 26 cmd_out2 = cmd_out1[1].split('`') 27 if cmd_out2 != 0: 28 cmd_out3 = cmd_out2[1].split(' at') 29 if len(cmd_out3) != 0: 30 symbol_str = "{:#018x} <{:s}>".format(unsigned(a), cmd_out3[0]) 31 return symbol_str 32 return "" 33 34@lldb_command('xi') 35def SymbolicateWithInstruction(cmd_args=None): 36 """ Prints out address and symbol similar to x/i 37 Usage: xi <address whose symbol is needed> 38 """ 39 if not cmd_args: 40 print("No arguments passed") 41 print(SymbolicateWithInstruction.__doc__) 42 return False 43 a = ArgumentStringToInt(cmd_args[0]) 44 print(OutputAddress([a])) 45 46# Macro: xi 47 48# Macro: newbt 49@lldb_command('newbt') 50def NewBt(cmd_args=None): 51 """ Prints all the instructions by walking the given stack pointer 52 """ 53 if not cmd_args: 54 print("No arguments passed") 55 print(NewBt.__doc__) 56 return False 57 a = ArgumentStringToInt(cmd_args[0]) 58 while a != 0: 59 if kern.arch == "x86_64" or kern.arch.startswith("arm64"): 60 offset = 8 61 else: 62 offset = 4 63 link_register = dereference(kern.GetValueFromAddress(a + offset, 'uintptr_t *')) 64 cmd_str = "di -s {:#x} -c 1".format(link_register) 65 cmd_out = lldb_run_command(cmd_str) 66 if len(cmd_out) != 0: 67 cmd_out1 = list(filter(None, cmd_out.split('\n'))) 68 if len(cmd_out1) != 0: 69 address = OutputAddress([unsigned(link_register)]) 70 if not address: 71 address = '{:#018x} <???>'.format(unsigned(link_register)) 72 print(address + ": " + cmd_out1[-1].split(':', 1)[1]) 73 a = dereference(kern.GetValueFromAddress(unsigned(a), 'uintptr_t *')) 74 75# EndMacro: newbt 76 77# Macro: parseLR 78@lldb_command('parseLR') 79def parseLR(cmd_args=None): 80 """ Decode the LR value from panic log into source code location 81 """ 82 global paniclog_data 83 panic_found = 1 84 85 if not paniclog_data: 86 if kern.arch == "x86_64": 87 paniclog_data += returnfunc("\n(lldb) paniclog\n", "paniclog -v") 88 else: 89 paniclog_data += returnfunc("\n(lldb) paniclog\n", "paniclog") 90 91 if panic_found == 1: 92 srch_string = "lr:\s+0x[a-fA-F0-9]+\s" 93 lr_pc_srch = re.findall(srch_string, paniclog_data) 94 if lr_pc_srch: 95 print(paniclog_data, lr_pc_srch) 96 for match in lr_pc_srch: 97 sp=match.strip("lr: ") 98 print(sp) 99 print("(lldb) list *{:s}".format(sp)) 100 print(lldb_run_command("list *{:s}".format(sp))) 101 102 else: 103 print("Currently unsupported on x86_64 architecture") 104#EndMacro: parseLR 105 106# Macro: parseLRfromfile 107@lldb_command('parseLRfromfile') 108def parseLRfromfile(cmd_args=None): 109 """ Decode the LR value from file into source code location 110 """ 111 f = open('/tmp/lrparsefile', 'r') 112 parse_data= f.read() 113 srch_string = "lr:\s+0x[a-fA-F0-9]+\s" 114 lr_pc_srch = re.findall(srch_string, parse_data) 115 if lr_pc_srch: 116 print(paniclog_data, lr_pc_srch) 117 for match in lr_pc_srch: 118 sp=match.strip("lr: ") 119 print(sp) 120 print("(lldb) list *{:s}".format(sp)) 121 print(lldb_run_command("list *{:s}".format(sp))) 122 123#EndMacro: parseLRfromfile 124 125