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