xref: /kvm-unit-tests/scripts/pretty_print_stacks.py (revision a9143a24a8ec26c0143678bbe0c41a63812091d3)
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