From: Dmitry Voytik <dmitry.voy...@huawei.com> Add ./scripts/arm64-parsedump.py tool. This tool decodes an ARM64 exception dump and prints human-readable stack trace like this:
[0x00000000fc008688] arch_handle_dabt mmio.c:97 [0x00000000fc009acc] arch_handle_trap traps.c:143 The tool can read dumps from files (passed via -f parameter) or from stdin stream (which can be also piped-in). Signed-off-by: Dmitry Voytik <dmitry.voy...@huawei.com> Signed-off-by: Jan Kiszka <jan.kis...@siemens.com> --- scripts/arm64-parsedump.py | 167 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100755 scripts/arm64-parsedump.py diff --git a/scripts/arm64-parsedump.py b/scripts/arm64-parsedump.py new file mode 100755 index 0000000..9519eb5 --- /dev/null +++ b/scripts/arm64-parsedump.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python + +# Jailhouse, a Linux-based partitioning hypervisor +# +# Copyright (C) 2015-2016 Huawei Technologies Duesseldorf GmbH +# +# Authors: +# Dmitry Voytik <dmitry.voy...@huawei.com> +# +# ARM64 dump parser. +# Usage ./scripts/arm64-parsedump.py [dump.txt] +# +# This work is licensed under the terms of the GNU GPL, version 2. See +# the COPYING file in the top-level directory. + + +from __future__ import print_function +import subprocess +import sys +import fileinput +import os +import argparse + +split1 = "Cell's stack before exception " +split2 = "Hypervisor stack before exception " + + +# yep, this is most important feature +class Col: + ENDC = '\033[0m' + BOLD = '\033[1m' + FAIL = '\033[91m' + + @staticmethod + def init(): + t = os.environ['TERM'] + if t == '' or t == 'dumb' or t == 'vt220' or t == 'vt100': + # The terminal doesn't support colors + Col.ENDC = '' + Col.BOLD = '' + Col.FAIL = '' + + @staticmethod + def bold(string): + return Col.BOLD + str(string) + Col.ENDC + + @staticmethod + def pr_err(string): + print(Col.FAIL + "ERROR: " + Col.ENDC + str(string)) + + @staticmethod + def pr_note(string): + print(Col.BOLD + "NOTE: " + Col.ENDC + str(string)) + + +def addr2line(addr): + return subprocess.check_output(["addr2line", "-a", "-f", "-p", "-e", + objpath, hex(addr)]) + + +def print_faddr(addr): + s = str(addr2line(addr)) + if s.find("?") != -1: + print("[{:#016x}] {}".format(addr, Col.bold("uknown"))) + return + s = s.strip().split(" ") + print("[{}] {} {}".format(s[0][:-1], Col.bold(s[1]), + s[3].split('/')[-1])) + + +class Dump: + def __init__(self, dump_str): + if len(dump_str) < 50: + raise ValueError('Dump is too small') + # parse CPU state + pc_i = dump_str.find("pc:") + 4 + self.pc = int(dump_str[pc_i: pc_i+16], 16) + pc_i = dump_str.find("sp:") + 4 + self.sp = int(dump_str[pc_i: pc_i+16], 16) + el_i = dump_str.rfind("EL") + 2 + self.el = int(dump_str[el_i:el_i+1]) + if (self.el != 2): + Col.pr_err("This version supports only EL2 exception dump") + + # TODO: parse other registers: ESR, etc + + # parse stack dump + stack_start = str.rfind(dump_str, split1) + if (stack_start == -1): + stack_start = str.rfind(dump_str, split2) + if (stack_start == -1): + raise ValueError('Dump is damaged') + + stack_str = dump_str[stack_start:].strip().split('\n') + stack_addr_start = int(stack_str[0][35:53], 16) + stack_addr_end = int(stack_str[0][56:74], 16) + + # parse stack memory dump + stack = [] + for line in stack_str[1:]: + if (len(line) < 5): + continue + if (line[4] != ':'): + continue + line = line[5:].strip().split(" ") + for value in line: + stack.append(int(value, 16)) + + self.stack_mem = stack + self.stack_start = stack_addr_start + self.stack_end = stack_addr_end + + def stack_get64(self, addr): + assert addr >= self.sp + i = int((addr - self.sp) / 4) + hi32 = self.stack_mem[i] + lo32 = self.stack_mem[i + 1] + return lo32 + (hi32 << 32) + + def print_unwinded_stack(self): + print_faddr(self.pc) + addr = self.sp + while True: + prev_sp = self.stack_get64(addr) + print_faddr(self.stack_get64(addr+4)) + addr = prev_sp + if (addr > self.stack_end - 256): + break + + +def main(): + Col.init() + + parser = argparse.ArgumentParser(description='ARM64 exception dump parser') + parser.add_argument('--objpath', '-o', default="./hypervisor/hypervisor.o", + type=str, help="Path to hypervisor.o file") + parser.add_argument('-f', '--filedump', default="", type=str, + help="Exception dump text file") + args = parser.parse_args() + + global objpath + objpath = args.objpath + + stdin_used = False + infile = [args.filedump] + if args.filedump == "": + infile = [] + Col.pr_note("Input dumped text then press Enter, Control+D, Control+D") + stdin_used = True + + ilines = [] + for line in fileinput.input(infile): + ilines.append(line) + dump_str = "".join(ilines) + if (not stdin_used): + print(dump_str) + else: + print("\n") + try: + dump = Dump(dump_str) + except ValueError as err: + Col.pr_err(err) + return + dump.print_unwinded_stack() + +if __name__ == "__main__": + main() -- 2.1.4 -- You received this message because you are subscribed to the Google Groups "Jailhouse" group. To unsubscribe from this group and stop receiving emails from it, send an email to jailhouse-dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.