119f71b8eSPaolo Bonzini#!/usr/bin/env python3 2a9143a24SPeter Feiner 3a9143a24SPeter Feinerimport re 4a9143a24SPeter Feinerimport subprocess 5a9143a24SPeter Feinerimport sys 6a9143a24SPeter Feinerimport traceback 702d8befeSNina Schoetterl-Glauschimport os 8a9143a24SPeter Feiner 9e593c4fdSAndrew Jonesconfig = {} 10e593c4fdSAndrew Jones 11a9143a24SPeter Feiner# Subvert output buffering. 12a9143a24SPeter Feinerdef puts(string): 13a9143a24SPeter Feiner sys.stdout.write(string) 14a9143a24SPeter Feiner sys.stdout.flush() 15a9143a24SPeter Feiner 16a9143a24SPeter Feinerdef pretty_print_stack(binary, line): 17a9143a24SPeter Feiner addrs = line.split()[1:] 18a9143a24SPeter Feiner # Addresses are return addresses unless preceded by a '@'. We want the 19a9143a24SPeter Feiner # caller address so line numbers are more intuitive. Thus we subtract 1 20a9143a24SPeter Feiner # from the address to get the call code. 21a9143a24SPeter Feiner for i in range(len(addrs)): 22a9143a24SPeter Feiner addr = addrs[i] 23a9143a24SPeter Feiner if addr.startswith('@'): 24a9143a24SPeter Feiner addrs[i] = addr[1:] 25a9143a24SPeter Feiner else: 2632e7ba06SNina Schoetterl-Glausch addrs[i] = '%lx' % max((int(addrs[i], 16) - 1), 0) 27a9143a24SPeter Feiner 28a9143a24SPeter Feiner # Output like this: 2902d8befeSNina Schoetterl-Glausch # 0x004002be: start64 at path/to/kvm-unit-tests-repo-worktree/x86/cstart64.S:208 3002d8befeSNina Schoetterl-Glausch # (inlined by) test_ept_violation at path/to/kvm-unit-tests-repo-worktree/x86/vmx_tests.c:1719 (discriminator 1) 31e593c4fdSAndrew Jones cmd = [config.get('ADDR2LINE', 'addr2line'), '-e', binary, '-i', '-f', '--pretty', '--address'] 32a9143a24SPeter Feiner cmd.extend(addrs) 33a9143a24SPeter Feiner 34a9143a24SPeter Feiner p = subprocess.Popen(cmd, stdout=subprocess.PIPE) 35a9143a24SPeter Feiner out, err = p.communicate() 36a9143a24SPeter Feiner if p.returncode != 0: 37a9143a24SPeter Feiner puts(line) 38a9143a24SPeter Feiner return 39a9143a24SPeter Feiner 40a9143a24SPeter Feiner for line in out.splitlines(): 41*3c1736b1SThomas Huth m = re.match(rb'(.*) at (.*):(([0-9]+)|\?)([^:]*)', line) 42a9143a24SPeter Feiner if m is None: 43a9143a24SPeter Feiner puts('%s\n' % line) 44a9143a24SPeter Feiner return 45a9143a24SPeter Feiner 463ad01e61SNina Schoetterl-Glausch head, path, maybeline, line, tail = m.groups() 4702d8befeSNina Schoetterl-Glausch path = os.path.relpath(os.path.realpath(path), start=os.path.realpath(os.getcwdb())) 483ad01e61SNina Schoetterl-Glausch puts('%s at %s:%s%s\n' % (head.decode(), path.decode(), maybeline.decode(), tail.decode())) 493ad01e61SNina Schoetterl-Glausch if line: 50a9143a24SPeter Feiner line = int(line) 51a9143a24SPeter Feiner try: 52a9143a24SPeter Feiner lines = open(path).readlines() 53a9143a24SPeter Feiner except IOError: 54a9143a24SPeter Feiner continue 55a9143a24SPeter Feiner if line > 1: 56a9143a24SPeter Feiner puts(' %s\n' % lines[line - 2].rstrip()) 57a9143a24SPeter Feiner puts(' > %s\n' % lines[line - 1].rstrip()) 58a9143a24SPeter Feiner if line < len(lines): 59a9143a24SPeter Feiner puts(' %s\n' % lines[line].rstrip()) 60a9143a24SPeter Feiner 61a9143a24SPeter Feinerdef main(): 62a9143a24SPeter Feiner if len(sys.argv) != 2: 63a9143a24SPeter Feiner sys.stderr.write('usage: %s <kernel>\n' % sys.argv[0]) 64a9143a24SPeter Feiner sys.exit(1) 65a9143a24SPeter Feiner 6696875e96SAndrew Jones binary = sys.argv[1] 6796875e96SAndrew Jones if binary.endswith('.flat'): 6896875e96SAndrew Jones binary = binary.replace('.flat', '.elf') 6996875e96SAndrew Jones elif binary.endswith('.efi'): 7096875e96SAndrew Jones binary += '.debug' 71a9143a24SPeter Feiner 72e593c4fdSAndrew Jones with open("config.mak") as config_file: 73e593c4fdSAndrew Jones for line in config_file: 74e593c4fdSAndrew Jones name, val = line.partition("=")[::2] 75e593c4fdSAndrew Jones config[name.strip()] = val.strip() 76e593c4fdSAndrew Jones 77a9143a24SPeter Feiner try: 78a9143a24SPeter Feiner while True: 79a9143a24SPeter Feiner # Subvert input buffering. 80a9143a24SPeter Feiner line = sys.stdin.readline() 81a9143a24SPeter Feiner if line == '': 82a9143a24SPeter Feiner break 83a9143a24SPeter Feiner 84a9143a24SPeter Feiner puts(line) 85762f9cd8SAndrew Jones 86762f9cd8SAndrew Jones if not line.strip().startswith('STACK:'): 87a9143a24SPeter Feiner continue 88a9143a24SPeter Feiner 89a9143a24SPeter Feiner try: 90a9143a24SPeter Feiner pretty_print_stack(binary, line) 91a9143a24SPeter Feiner except Exception: 92a9143a24SPeter Feiner puts('Error pretty printing stack:\n') 93a9143a24SPeter Feiner puts(traceback.format_exc()) 94a9143a24SPeter Feiner puts('Continuing without pretty printing...\n') 95a9143a24SPeter Feiner while True: 96a9143a24SPeter Feiner puts(line) 97a9143a24SPeter Feiner line = sys.stdin.readline() 98a9143a24SPeter Feiner if line == '': 99a9143a24SPeter Feiner break 100a9143a24SPeter Feiner except: 101a9143a24SPeter Feiner sys.exit(1) 102a9143a24SPeter Feiner 103a9143a24SPeter Feinerif __name__ == '__main__': 104a9143a24SPeter Feiner main() 105