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