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