119f71b8eSPaolo Bonzini#!/usr/bin/env python3 2a9143a24SPeter Feiner 3a9143a24SPeter Feinerimport re 4a9143a24SPeter Feinerimport subprocess 5a9143a24SPeter Feinerimport sys 6a9143a24SPeter Feinerimport traceback 7a9143a24SPeter Feiner 8e593c4fdSAndrew Jonesconfig = {} 9e593c4fdSAndrew Jones 10a9143a24SPeter Feiner# Subvert output buffering. 11a9143a24SPeter Feinerdef puts(string): 12a9143a24SPeter Feiner sys.stdout.write(string) 13a9143a24SPeter Feiner sys.stdout.flush() 14a9143a24SPeter Feiner 15a9143a24SPeter Feinerdef pretty_print_stack(binary, line): 16a9143a24SPeter Feiner addrs = line.split()[1:] 17a9143a24SPeter Feiner # Addresses are return addresses unless preceded by a '@'. We want the 18a9143a24SPeter Feiner # caller address so line numbers are more intuitive. Thus we subtract 1 19a9143a24SPeter Feiner # from the address to get the call code. 20a9143a24SPeter Feiner for i in range(len(addrs)): 21a9143a24SPeter Feiner addr = addrs[i] 22a9143a24SPeter Feiner if addr.startswith('@'): 23a9143a24SPeter Feiner addrs[i] = addr[1:] 24a9143a24SPeter Feiner else: 25*32e7ba06SNina Schoetterl-Glausch addrs[i] = '%lx' % max((int(addrs[i], 16) - 1), 0) 26a9143a24SPeter Feiner 27a9143a24SPeter Feiner # Output like this: 28a9143a24SPeter Feiner # 0x004002be: start64 at path/to/kvm-unit-tests/x86/cstart64.S:208 29a9143a24SPeter Feiner # (inlined by) test_ept_violation at path/to/kvm-unit-tests/x86/vmx_tests.c:1719 (discriminator 1) 30e593c4fdSAndrew Jones cmd = [config.get('ADDR2LINE', 'addr2line'), '-e', binary, '-i', '-f', '--pretty', '--address'] 31a9143a24SPeter Feiner cmd.extend(addrs) 32a9143a24SPeter Feiner 33a9143a24SPeter Feiner p = subprocess.Popen(cmd, stdout=subprocess.PIPE) 34a9143a24SPeter Feiner out, err = p.communicate() 35a9143a24SPeter Feiner if p.returncode != 0: 36a9143a24SPeter Feiner puts(line) 37a9143a24SPeter Feiner return 38a9143a24SPeter Feiner 39a9143a24SPeter Feiner for line in out.splitlines(): 408951e978SPaolo Bonzini m = re.match(b'(.*) at [^ ]*/kvm-unit-tests/([^ ]*):([0-9]+)(.*)', line) 41a9143a24SPeter Feiner if m is None: 42a9143a24SPeter Feiner puts('%s\n' % line) 43a9143a24SPeter Feiner return 44a9143a24SPeter Feiner 45a9143a24SPeter Feiner head, path, line, tail = m.groups() 46a9143a24SPeter Feiner line = int(line) 478951e978SPaolo Bonzini puts('%s at %s:%d%s\n' % (head.decode(), path.decode(), line, tail.decode())) 48a9143a24SPeter Feiner try: 49a9143a24SPeter Feiner lines = open(path).readlines() 50a9143a24SPeter Feiner except IOError: 51a9143a24SPeter Feiner continue 52a9143a24SPeter Feiner if line > 1: 53a9143a24SPeter Feiner puts(' %s\n' % lines[line - 2].rstrip()) 54a9143a24SPeter Feiner puts(' > %s\n' % lines[line - 1].rstrip()) 55a9143a24SPeter Feiner if line < len(lines): 56a9143a24SPeter Feiner puts(' %s\n' % lines[line].rstrip()) 57a9143a24SPeter Feiner 58a9143a24SPeter Feinerdef main(): 59a9143a24SPeter Feiner if len(sys.argv) != 2: 60a9143a24SPeter Feiner sys.stderr.write('usage: %s <kernel>\n' % sys.argv[0]) 61a9143a24SPeter Feiner sys.exit(1) 62a9143a24SPeter Feiner 63e1f45419SAndrew Jones binary = sys.argv[1].replace(".flat", ".elf") 64a9143a24SPeter Feiner 65e593c4fdSAndrew Jones with open("config.mak") as config_file: 66e593c4fdSAndrew Jones for line in config_file: 67e593c4fdSAndrew Jones name, val = line.partition("=")[::2] 68e593c4fdSAndrew Jones config[name.strip()] = val.strip() 69e593c4fdSAndrew Jones 70a9143a24SPeter Feiner try: 71a9143a24SPeter Feiner while True: 72a9143a24SPeter Feiner # Subvert input buffering. 73a9143a24SPeter Feiner line = sys.stdin.readline() 74a9143a24SPeter Feiner if line == '': 75a9143a24SPeter Feiner break 76a9143a24SPeter Feiner 77a9143a24SPeter Feiner puts(line) 78762f9cd8SAndrew Jones 79762f9cd8SAndrew Jones if not line.strip().startswith('STACK:'): 80a9143a24SPeter Feiner continue 81a9143a24SPeter Feiner 82a9143a24SPeter Feiner try: 83a9143a24SPeter Feiner pretty_print_stack(binary, line) 84a9143a24SPeter Feiner except Exception: 85a9143a24SPeter Feiner puts('Error pretty printing stack:\n') 86a9143a24SPeter Feiner puts(traceback.format_exc()) 87a9143a24SPeter Feiner puts('Continuing without pretty printing...\n') 88a9143a24SPeter Feiner while True: 89a9143a24SPeter Feiner puts(line) 90a9143a24SPeter Feiner line = sys.stdin.readline() 91a9143a24SPeter Feiner if line == '': 92a9143a24SPeter Feiner break 93a9143a24SPeter Feiner except: 94a9143a24SPeter Feiner sys.exit(1) 95a9143a24SPeter Feiner 96a9143a24SPeter Feinerif __name__ == '__main__': 97a9143a24SPeter Feiner main() 98