diff mbox

[kvm-unit-tests,v3,4/4] scripts: pretty print stack traces

Message ID 1457038116-3448-5-git-send-email-pfeiner@google.com (mailing list archive)
State New, archived
Headers show

Commit Message

Peter Feiner March 3, 2016, 8:48 p.m. UTC
Optionally pretty print stacks in test.log with 'run_tests.sh -p'.

The script runs addresses through addr2line to get file names and line
numbers.  Also prints out source code lines if files are available.
For example

0x004013f5: ac_test_exec at x86/access.c:818
            }
      >     ac_test_setup_pte(at, pool);
            r = ac_test_do_access(at);
0x004014dd: ac_test_run at x86/access.c:852
                ++tests;
      >         successes += ac_test_exec(&at, &pool);
            } while (ac_test_bump(&at));
0x0040157d: main at x86/access.c:873
            printf("starting test\n\n");
      >     r = ac_test_run();
            return r ? 0 : 1;
0x0040028e: start64 at x86/cstart64.S:206
                lea __argv(%rip), %rsi
      >         call main
                mov %eax, %edi

Signed-off-by: Peter Feiner <pfeiner@google.com>
---
 run_tests.sh                   | 10 ++++-
 scripts/pretty_print_stacks.py | 89 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 97 insertions(+), 2 deletions(-)
 create mode 100755 scripts/pretty_print_stacks.py

Comments

Andrew Jones March 4, 2016, 10:24 a.m. UTC | #1
On Thu, Mar 03, 2016 at 12:48:36PM -0800, Peter Feiner wrote:
> Optionally pretty print stacks in test.log with 'run_tests.sh -p'.
> 
> The script runs addresses through addr2line to get file names and line
> numbers.  Also prints out source code lines if files are available.
> For example
> 
> 0x004013f5: ac_test_exec at x86/access.c:818
>             }
>       >     ac_test_setup_pte(at, pool);
>             r = ac_test_do_access(at);
> 0x004014dd: ac_test_run at x86/access.c:852
>                 ++tests;
>       >         successes += ac_test_exec(&at, &pool);
>             } while (ac_test_bump(&at));
> 0x0040157d: main at x86/access.c:873
>             printf("starting test\n\n");
>       >     r = ac_test_run();
>             return r ? 0 : 1;
> 0x0040028e: start64 at x86/cstart64.S:206
>                 lea __argv(%rip), %rsi
>       >         call main
>                 mov %eax, %edi
> 
> Signed-off-by: Peter Feiner <pfeiner@google.com>
> ---
>  run_tests.sh                   | 10 ++++-
>  scripts/pretty_print_stacks.py | 89 ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 97 insertions(+), 2 deletions(-)
>  create mode 100755 scripts/pretty_print_stacks.py
> 
> diff --git a/run_tests.sh b/run_tests.sh
> index 89e8f84..b6f2003 100755
> --- a/run_tests.sh
> +++ b/run_tests.sh
> @@ -1,6 +1,7 @@
>  #!/bin/bash
>  
>  verbose="no"
> +pretty="no"
>  
>  if [ ! -f config.mak ]; then
>      echo "run ./configure && make first. See ./configure -h"
> @@ -18,6 +19,7 @@ Usage: $0 [-g group] [-h] [-v]
>      -g: Only execute tests in the given group
>      -h: Output this help text
>      -v: Enables verbose mode
> +    -p: Pretty print stack traces in test.log
>  
>  Set the environment variable QEMU=/path/to/qemu-system-ARCH to
>  specify the appropriate qemu binary for ARCH-run.
> @@ -27,8 +29,9 @@ EOF
>  
>  RUNTIME_arch_run="./$TEST_DIR/run"
>  source scripts/runtime.bash
> +log_redir=">> test.log"
>  
> -while getopts "g:hv" opt; do
> +while getopts "g:hvp" opt; do
>      case $opt in
>          g)
>              only_group=$OPTARG
> @@ -40,13 +43,16 @@ while getopts "g:hv" opt; do
>          v)
>              verbose="yes"
>              ;;
> +        p)
> +           log_redir="> >(./scripts/pretty_print_stacks.py \$kernel >> test.log)"
> +           ;;

What about the idea of turning this on by default, and only turning it
off if it was configured off?

drew
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Peter Feiner March 4, 2016, 4:55 p.m. UTC | #2
On Fri, Mar 4, 2016 at 2:24 AM, Andrew Jones <drjones@redhat.com> wrote:
> On Thu, Mar 03, 2016 at 12:48:36PM -0800, Peter Feiner wrote:
>> Optionally pretty print stacks in test.log with 'run_tests.sh -p'.
>>
>> The script runs addresses through addr2line to get file names and line
>> numbers.  Also prints out source code lines if files are available.
>> For example
>>
>> 0x004013f5: ac_test_exec at x86/access.c:818
>>             }
>>       >     ac_test_setup_pte(at, pool);
>>             r = ac_test_do_access(at);
>> 0x004014dd: ac_test_run at x86/access.c:852
>>                 ++tests;
>>       >         successes += ac_test_exec(&at, &pool);
>>             } while (ac_test_bump(&at));
>> 0x0040157d: main at x86/access.c:873
>>             printf("starting test\n\n");
>>       >     r = ac_test_run();
>>             return r ? 0 : 1;
>> 0x0040028e: start64 at x86/cstart64.S:206
>>                 lea __argv(%rip), %rsi
>>       >         call main
>>                 mov %eax, %edi
>>
>> Signed-off-by: Peter Feiner <pfeiner@google.com>
>> ---
>>  run_tests.sh                   | 10 ++++-
>>  scripts/pretty_print_stacks.py | 89 ++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 97 insertions(+), 2 deletions(-)
>>  create mode 100755 scripts/pretty_print_stacks.py
>>
>> diff --git a/run_tests.sh b/run_tests.sh
>> index 89e8f84..b6f2003 100755
>> --- a/run_tests.sh
>> +++ b/run_tests.sh
>> @@ -1,6 +1,7 @@
>>  #!/bin/bash
>>
>>  verbose="no"
>> +pretty="no"
>>
>>  if [ ! -f config.mak ]; then
>>      echo "run ./configure && make first. See ./configure -h"
>> @@ -18,6 +19,7 @@ Usage: $0 [-g group] [-h] [-v]
>>      -g: Only execute tests in the given group
>>      -h: Output this help text
>>      -v: Enables verbose mode
>> +    -p: Pretty print stack traces in test.log
>>
>>  Set the environment variable QEMU=/path/to/qemu-system-ARCH to
>>  specify the appropriate qemu binary for ARCH-run.
>> @@ -27,8 +29,9 @@ EOF
>>
>>  RUNTIME_arch_run="./$TEST_DIR/run"
>>  source scripts/runtime.bash
>> +log_redir=">> test.log"
>>
>> -while getopts "g:hv" opt; do
>> +while getopts "g:hvp" opt; do
>>      case $opt in
>>          g)
>>              only_group=$OPTARG
>> @@ -40,13 +43,16 @@ while getopts "g:hv" opt; do
>>          v)
>>              verbose="yes"
>>              ;;
>> +        p)
>> +           log_redir="> >(./scripts/pretty_print_stacks.py \$kernel >> test.log)"
>> +           ;;
>
> What about the idea of turning this on by default, and only turning it
> off if it was configured off?

I was waiting for the config option to be added. I had thought you
were going to send that patch. I'll add the config option to the
series and make it on-by-default.

Peter
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Andrew Jones March 4, 2016, 6:43 p.m. UTC | #3
On Fri, Mar 04, 2016 at 08:55:59AM -0800, Peter Feiner wrote:
> On Fri, Mar 4, 2016 at 2:24 AM, Andrew Jones <drjones@redhat.com> wrote:
> > On Thu, Mar 03, 2016 at 12:48:36PM -0800, Peter Feiner wrote:
> >> Optionally pretty print stacks in test.log with 'run_tests.sh -p'.
> >>
> >> The script runs addresses through addr2line to get file names and line
> >> numbers.  Also prints out source code lines if files are available.
> >> For example
> >>
> >> 0x004013f5: ac_test_exec at x86/access.c:818
> >>             }
> >>       >     ac_test_setup_pte(at, pool);
> >>             r = ac_test_do_access(at);
> >> 0x004014dd: ac_test_run at x86/access.c:852
> >>                 ++tests;
> >>       >         successes += ac_test_exec(&at, &pool);
> >>             } while (ac_test_bump(&at));
> >> 0x0040157d: main at x86/access.c:873
> >>             printf("starting test\n\n");
> >>       >     r = ac_test_run();
> >>             return r ? 0 : 1;
> >> 0x0040028e: start64 at x86/cstart64.S:206
> >>                 lea __argv(%rip), %rsi
> >>       >         call main
> >>                 mov %eax, %edi
> >>
> >> Signed-off-by: Peter Feiner <pfeiner@google.com>
> >> ---
> >>  run_tests.sh                   | 10 ++++-
> >>  scripts/pretty_print_stacks.py | 89 ++++++++++++++++++++++++++++++++++++++++++
> >>  2 files changed, 97 insertions(+), 2 deletions(-)
> >>  create mode 100755 scripts/pretty_print_stacks.py
> >>
> >> diff --git a/run_tests.sh b/run_tests.sh
> >> index 89e8f84..b6f2003 100755
> >> --- a/run_tests.sh
> >> +++ b/run_tests.sh
> >> @@ -1,6 +1,7 @@
> >>  #!/bin/bash
> >>
> >>  verbose="no"
> >> +pretty="no"
> >>
> >>  if [ ! -f config.mak ]; then
> >>      echo "run ./configure && make first. See ./configure -h"
> >> @@ -18,6 +19,7 @@ Usage: $0 [-g group] [-h] [-v]
> >>      -g: Only execute tests in the given group
> >>      -h: Output this help text
> >>      -v: Enables verbose mode
> >> +    -p: Pretty print stack traces in test.log
> >>
> >>  Set the environment variable QEMU=/path/to/qemu-system-ARCH to
> >>  specify the appropriate qemu binary for ARCH-run.
> >> @@ -27,8 +29,9 @@ EOF
> >>
> >>  RUNTIME_arch_run="./$TEST_DIR/run"
> >>  source scripts/runtime.bash
> >> +log_redir=">> test.log"
> >>
> >> -while getopts "g:hv" opt; do
> >> +while getopts "g:hvp" opt; do
> >>      case $opt in
> >>          g)
> >>              only_group=$OPTARG
> >> @@ -40,13 +43,16 @@ while getopts "g:hv" opt; do
> >>          v)
> >>              verbose="yes"
> >>              ;;
> >> +        p)
> >> +           log_redir="> >(./scripts/pretty_print_stacks.py \$kernel >> test.log)"
> >> +           ;;
> >
> > What about the idea of turning this on by default, and only turning it
> > off if it was configured off?
> 
> I was waiting for the config option to be added. I had thought you
> were going to send that patch. I'll add the config option to the
> series and make it on-by-default.

Ah, yeah, I was thinking you'd do it, since the '-p' option can just be
dropped, once we have it on by default, and thus no reason to commit this,
and then commit a patch taking it away.

Thanks,
drew


> 
> Peter
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/run_tests.sh b/run_tests.sh
index 89e8f84..b6f2003 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -1,6 +1,7 @@ 
 #!/bin/bash
 
 verbose="no"
+pretty="no"
 
 if [ ! -f config.mak ]; then
     echo "run ./configure && make first. See ./configure -h"
@@ -18,6 +19,7 @@  Usage: $0 [-g group] [-h] [-v]
     -g: Only execute tests in the given group
     -h: Output this help text
     -v: Enables verbose mode
+    -p: Pretty print stack traces in test.log
 
 Set the environment variable QEMU=/path/to/qemu-system-ARCH to
 specify the appropriate qemu binary for ARCH-run.
@@ -27,8 +29,9 @@  EOF
 
 RUNTIME_arch_run="./$TEST_DIR/run"
 source scripts/runtime.bash
+log_redir=">> test.log"
 
-while getopts "g:hv" opt; do
+while getopts "g:hvp" opt; do
     case $opt in
         g)
             only_group=$OPTARG
@@ -40,13 +43,16 @@  while getopts "g:hv" opt; do
         v)
             verbose="yes"
             ;;
+        p)
+           log_redir="> >(./scripts/pretty_print_stacks.py \$kernel >> test.log)"
+           ;;
         *)
             exit 1
             ;;
     esac
 done
 
-RUNTIME_arch_run="./$TEST_DIR/run >> test.log"
+RUNTIME_arch_run="./$TEST_DIR/run $log_redir"
 config=$TEST_DIR/unittests.cfg
 rm -f test.log
 printf "BUILD_HEAD=$(cat build-head)\n\n" > test.log
diff --git a/scripts/pretty_print_stacks.py b/scripts/pretty_print_stacks.py
new file mode 100755
index 0000000..ee5a52e
--- /dev/null
+++ b/scripts/pretty_print_stacks.py
@@ -0,0 +1,89 @@ 
+#!/usr/bin/env python
+
+import re
+import subprocess
+import sys
+import traceback
+
+# Subvert output buffering.
+def puts(string):
+    sys.stdout.write(string)
+    sys.stdout.flush()
+
+def pretty_print_stack(binary, line):
+    addrs = line.split()[1:]
+    # Addresses are return addresses unless preceded by a '@'. We want the
+    # caller address so line numbers are more intuitive. Thus we subtract 1
+    # from the address to get the call code.
+    for i in range(len(addrs)):
+        addr = addrs[i]
+        if addr.startswith('@'):
+            addrs[i] = addr[1:]
+        else:
+            addrs[i] = '%lx' % (int(addrs[i], 16) - 1)
+
+    # Output like this:
+    #        0x004002be: start64 at path/to/kvm-unit-tests/x86/cstart64.S:208
+    #         (inlined by) test_ept_violation at path/to/kvm-unit-tests/x86/vmx_tests.c:1719 (discriminator 1)
+    cmd = ['addr2line', '-e', binary, '-i', '-f', '--pretty', '--address']
+    cmd.extend(addrs)
+
+    p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+    out, err = p.communicate()
+    if p.returncode != 0:
+        puts(line)
+        return
+
+    for line in out.splitlines():
+        m = re.match('(.*) at [^ ]*/kvm-unit-tests/([^ ]*):([0-9]+)(.*)', line)
+        if m is None:
+            puts('%s\n' % line)
+            return
+
+        head, path, line, tail = m.groups()
+        line = int(line)
+        puts('%s at %s:%d%s\n' % (head, path, line, tail))
+        try:
+            lines = open(path).readlines()
+        except IOError:
+            continue
+        if line > 1:
+            puts('        %s\n' % lines[line - 2].rstrip())
+        puts('      > %s\n' % lines[line - 1].rstrip())
+        if line < len(lines):
+            puts('        %s\n' % lines[line].rstrip())
+
+def main():
+    if len(sys.argv) != 2:
+        sys.stderr.write('usage: %s <kernel>\n' % sys.argv[0])
+        sys.exit(1)
+
+    binary = sys.argv[1]
+
+    try:
+        while True:
+            # Subvert input buffering.
+            line = sys.stdin.readline()
+            if line == '':
+                break
+
+            if not line.strip().startswith('STACK:'):
+                puts(line)
+                continue
+
+            try:
+                pretty_print_stack(binary, line)
+            except Exception:
+                puts('Error pretty printing stack:\n')
+                puts(traceback.format_exc())
+                puts('Continuing without pretty printing...\n')
+                while True:
+                    puts(line)
+                    line = sys.stdin.readline()
+                    if line == '':
+                        break
+    except:
+        sys.exit(1)
+
+if __name__ == '__main__':
+    main()