All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Jones <drjones@redhat.com>
To: Peter Feiner <pfeiner@google.com>
Cc: kvm@vger.kernel.org, pbonzini@redhat.com
Subject: Re: [PATCH kvm-unit-tests v5 1/5] lib: backtrace printing
Date: Tue, 8 Mar 2016 11:24:45 +0700	[thread overview]
Message-ID: <20160308042325.GB1638@localhost.redhat.com> (raw)
In-Reply-To: <757ca48dec7f6c497948468cb1da89ff646f2e28.1457372594.git.pfeiner@google.com>

On Mon, Mar 07, 2016 at 09:46:53AM -0800, Peter Feiner wrote:
> Functions to walk stack and print backtrace. The stack's unadorned as
> 
> 	STACK: [@]addr addr addr ...
> 
> where the optional @ indicates that addr isn't a return address.
> 
> A follow-up patch post-processes the output to pretty-print the stack.
> 
> Frame stack walker is just a stub on arm and ppc.
> 
> Signed-off-by: Peter Feiner <pfeiner@google.com>
> ---
>  Makefile                |  6 ++--
>  lib/arm/asm/stack.h     |  0
>  lib/arm64/asm/stack.h   |  0
>  lib/asm-generic/stack.c |  3 ++
>  lib/libcflat.h          |  3 ++
>  lib/powerpc/asm/stack.h |  0
>  lib/ppc64/asm/stack.h   |  0
>  lib/stack.c             | 96 +++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/stack.h             | 20 +++++++++++
>  lib/x86/asm/stack.h     | 18 ++++++++++
>  lib/x86/stack.c         | 25 +++++++++++++
>  x86/Makefile.common     |  4 +++
>  12 files changed, 173 insertions(+), 2 deletions(-)
>  create mode 100644 lib/arm/asm/stack.h
>  create mode 100644 lib/arm64/asm/stack.h
>  create mode 100644 lib/asm-generic/stack.c
>  create mode 100644 lib/powerpc/asm/stack.h
>  create mode 100644 lib/ppc64/asm/stack.h
>  create mode 100644 lib/stack.c
>  create mode 100644 lib/stack.h
>  create mode 100644 lib/x86/asm/stack.h
>  create mode 100644 lib/x86/stack.c
> 
> diff --git a/Makefile b/Makefile
> index 72e6711..c53aff6 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -22,7 +22,8 @@ cflatobjs := \
>  	lib/printf.o \
>  	lib/string.o \
>  	lib/abort.o \
> -	lib/report.o
> +	lib/report.o \
> +	lib/stack.o
>  
>  # libfdt paths
>  LIBFDT_objdir = lib/libfdt
> @@ -42,7 +43,8 @@ cc-option = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null \
>  
>  CFLAGS += -g
>  CFLAGS += $(autodepend-flags) -Wall
> -CFLAGS += $(call cc-option, -fomit-frame-pointer, "")
> +frame-pointer-flag=-f$(if $(KEEP_FRAME_POINTER),no-,)omit-frame-pointer
> +CFLAGS += $(call cc-option, $(frame-pointer-flag), "")
>  CFLAGS += $(call cc-option, -fno-stack-protector, "")
>  CFLAGS += $(call cc-option, -fno-stack-protector-all, "")
>  
> diff --git a/lib/arm/asm/stack.h b/lib/arm/asm/stack.h
> new file mode 100644
> index 0000000..e69de29
> diff --git a/lib/arm64/asm/stack.h b/lib/arm64/asm/stack.h
> new file mode 100644
> index 0000000..e69de29
> diff --git a/lib/asm-generic/stack.c b/lib/asm-generic/stack.c
> new file mode 100644
> index 0000000..40c67c2
> --- /dev/null
> +++ b/lib/asm-generic/stack.c
> @@ -0,0 +1,3 @@
> +#include <libcflat.h>
> +#include <asm-generic/stack.h>
> +

Looks like you forgot to remove this file.

> diff --git a/lib/libcflat.h b/lib/libcflat.h
> index b58a8a1..55bddca 100644
> --- a/lib/libcflat.h
> +++ b/lib/libcflat.h
> @@ -81,6 +81,9 @@ extern void report_xfail(const char *msg_fmt, bool xfail, bool pass, ...);
>  extern void report_abort(const char *msg_fmt, ...);
>  extern int report_summary(void);
>  
> +extern void dump_stack(void);
> +extern void dump_frame_stack(const void *instruction, const void *frame);
> +
>  #define ARRAY_SIZE(_a) (sizeof(_a)/sizeof((_a)[0]))
>  
>  #define container_of(ptr, type, member) ({				\
> diff --git a/lib/powerpc/asm/stack.h b/lib/powerpc/asm/stack.h
> new file mode 100644
> index 0000000..e69de29
> diff --git a/lib/ppc64/asm/stack.h b/lib/ppc64/asm/stack.h
> new file mode 100644
> index 0000000..e69de29
> diff --git a/lib/stack.c b/lib/stack.c
> new file mode 100644
> index 0000000..035fe27
> --- /dev/null
> +++ b/lib/stack.c
> @@ -0,0 +1,96 @@
> +#include <libcflat.h>
> +#include <stack.h>
> +
> +#define MAX_DEPTH 20
> +
> +static void print_stack(const void **return_addrs, int depth,
> +			bool top_is_return_address)
> +{
> +	int i = 0;
> +
> +	printf("\tSTACK:");
> +
> +	/* @addr indicates a non-return address, as expected by the stack
> +	 * pretty printer script. */
> +	if (depth > 0 && !top_is_return_address) {
> +		printf(" @%lx", (unsigned long) return_addrs[0]);
> +		i++;
> +	}
> +
> +	for (; i < depth; i++) {
> +		printf(" %lx", (unsigned long) return_addrs[i]);
> +	}
> +	printf("\n");
> +}
> +
> +void dump_stack(void)
> +{
> +	const void *return_addrs[MAX_DEPTH];
> +	int depth;
> +
> +	depth = backtrace(return_addrs, MAX_DEPTH);
> +	print_stack(return_addrs, depth, true);
> +}
> +
> +void dump_frame_stack(const void *instruction, const void *frame)
> +{
> +	const void *return_addrs[MAX_DEPTH];
> +	int depth;
> +
> +	return_addrs[0] = instruction;
> +	depth = backtrace_frame(frame, &return_addrs[1], MAX_DEPTH - 1);
> +	print_stack(return_addrs, depth + 1, false);
> +}
> +
> +#ifndef HAVE_ARCH_BACKTRACE
> +int backtrace(const void **return_addrs, int max_depth)
> +{
> +	static int walking;
> +	int depth = 0;
> +	void *addr;
> +
> +	if (walking) {
> +		printf("RECURSIVE STACK WALK!!!\n");
> +		return 0;
> +	}
> +	walking = 1;
> +
> +	/* __builtin_return_address requires a compile-time constant argument */
> +#define GET_RETURN_ADDRESS(i)						\
> +	if (max_depth == i)						\
> +		goto done;						\
> +	addr = __builtin_return_address(i + 1);				\

Is the +1 to skip a level, which means addr is an address two levels up?
If we do that, then won't we skip the callers of backtrace, which may or
may not be dump_stack?


> +	if (!addr)							\
> +		goto done;						\
> +	return_addrs[i] = __builtin_extract_return_addr(addr);		\

So here we put the i+1th return address into return_addrs[i]. I find
that a bit confusing. Maybe we should leave it to the callers of
backtrace to do any level skipping they want, i.e. here we shouldn't
skip anything, but dump_stack could start printing at i=1.


> +	depth = i + 1;							\
> +
> +	GET_RETURN_ADDRESS(0)
> +	GET_RETURN_ADDRESS(1)
> +	GET_RETURN_ADDRESS(2)
> +	GET_RETURN_ADDRESS(3)
> +	GET_RETURN_ADDRESS(4)
> +	GET_RETURN_ADDRESS(5)
> +	GET_RETURN_ADDRESS(6)
> +	GET_RETURN_ADDRESS(7)
> +	GET_RETURN_ADDRESS(8)
> +	GET_RETURN_ADDRESS(9)
> +	GET_RETURN_ADDRESS(10)
> +	GET_RETURN_ADDRESS(11)
> +	GET_RETURN_ADDRESS(12)
> +	GET_RETURN_ADDRESS(13)
> +	GET_RETURN_ADDRESS(14)
> +	GET_RETURN_ADDRESS(15)
> +	GET_RETURN_ADDRESS(16)
> +	GET_RETURN_ADDRESS(17)
> +	GET_RETURN_ADDRESS(18)
> +	GET_RETURN_ADDRESS(19)
> +	GET_RETURN_ADDRESS(20)
> +
> +#undef GET_RETURN_ADDRESS
> +
> +done:
> +	walking = 0;
> +	return depth;
> +}
> +#endif  /* HAVE_ARCH_BACKTRACE */
> diff --git a/lib/stack.h b/lib/stack.h
> new file mode 100644
> index 0000000..bb6b9aa
> --- /dev/null
> +++ b/lib/stack.h
> @@ -0,0 +1,20 @@
> +#ifndef _STACK_H_
> +#define _STACK_H_
> +
> +#include <libcflat.h>
> +#include <asm/stack.h>
> +
> +#ifndef HAVE_ARCH_BACKTRACE_FRAME
> +static inline int
> +backtrace_frame(const void *frame __unused, const void **return_addrs __unused,
> +		int max_depth __unused)
> +{
> +	return 0;
> +}
> +#endif
> +
> +#ifndef HAVE_ARCH_BACKTRACE
> +int backtrace(const void **return_addrs, int max_depth);
> +#endif
> +
> +#endif
> diff --git a/lib/x86/asm/stack.h b/lib/x86/asm/stack.h
> new file mode 100644
> index 0000000..bb1c2c0
> --- /dev/null
> +++ b/lib/x86/asm/stack.h
> @@ -0,0 +1,18 @@
> +#ifndef _X86ASM_STACK_H_
> +#define _X86ASM_STACK_H_
> +
> +#ifndef _STACK_H_
> +#error Do not directly include <asm/stack.h>. Just use <stack.h>.
> +#endif
> +
> +#define HAVE_ARCH_BACKTRACE_FRAME
> +int backtrace_frame(const void *frame, const void **return_addrs, int max_depth);
> +
> +#define HAVE_ARCH_BACKTRACE
> +static inline int backtrace(const void **return_addrs, int max_depth)
> +{
> +	return backtrace_frame(__builtin_frame_address(0), return_addrs,
> +			       max_depth);
> +}
> +
> +#endif
> diff --git a/lib/x86/stack.c b/lib/x86/stack.c
> new file mode 100644
> index 0000000..3227800
> --- /dev/null
> +++ b/lib/x86/stack.c
> @@ -0,0 +1,25 @@
> +#include <libcflat.h>
> +#include <stack.h>
> +
> +int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
> +{
> +	static int walking;
> +	int depth = 0;
> +	const unsigned long *bp = (unsigned long *) frame;
> +
> +	if (walking) {
> +		printf("RECURSIVE STACK WALK!!!\n");
> +		return 0;
> +	}
> +	walking = 1;
> +
> +	for (depth = 0; depth < max_depth; depth++) {
> +		return_addrs[depth] = (void *) bp[1];
> +		if (return_addrs[depth] == 0)
> +			break;
> +		bp = (unsigned long *) bp[0];
> +	}
> +
> +	walking = 0;
> +	return depth;
> +}
> diff --git a/x86/Makefile.common b/x86/Makefile.common
> index 3a14fea..ca80367 100644
> --- a/x86/Makefile.common
> +++ b/x86/Makefile.common
> @@ -12,6 +12,7 @@ cflatobjs += lib/x86/atomic.o
>  cflatobjs += lib/x86/desc.o
>  cflatobjs += lib/x86/isr.o
>  cflatobjs += lib/x86/acpi.o
> +cflatobjs += lib/x86/stack.o
>  
>  $(libcflat): LDFLAGS += -nostdlib
>  $(libcflat): CFLAGS += -ffreestanding -I lib
> @@ -19,6 +20,9 @@ $(libcflat): CFLAGS += -ffreestanding -I lib
>  CFLAGS += -m$(bits)
>  CFLAGS += -O1
>  
> +# dump_stack.o relies on frame pointers.
> +KEEP_FRAME_POINTER := y
> +
>  libgcc := $(shell $(CC) -m$(bits) --print-libgcc-file-name)
>  
>  FLATLIBS = lib/libcflat.a $(libgcc)
> -- 
> 2.7.0.rc3.207.g0ac5344
> 
> --
> 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

Thanks,
drew


  reply	other threads:[~2016-03-08  4:24 UTC|newest]

Thread overview: 65+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-01 21:27 [kvm-unit-tests 0/5] Debugging aids Peter Feiner
2016-03-01 21:27 ` [kvm-unit-tests 1/5] lib: print failing assert cond Peter Feiner
2016-03-02 15:04   ` Andrew Jones
2016-03-01 21:27 ` [kvm-unit-tests 2/5] lib: backtrace printing Peter Feiner
2016-03-01 22:58   ` Peter Feiner
2016-03-01 23:07     ` Peter Feiner
2016-03-01 21:27 ` [kvm-unit-tests 3/5] x86: lib: debug dump on unhandled exceptions Peter Feiner
2016-03-01 21:27 ` [kvm-unit-tests 4/5] lib: dump stack on abort() Peter Feiner
2016-03-01 21:29   ` Peter Feiner
2016-03-01 21:27 ` [kvm-unit-tests 5/5] scripts: pretty print stack traces Peter Feiner
2016-03-01 21:34   ` Paolo Bonzini
2016-03-03  9:35     ` Andrew Jones
2016-03-03 12:57       ` Paolo Bonzini
2016-03-03 13:38         ` Andrew Jones
2016-03-03  1:09 ` [kvm-unit-tests v2 0/8] Debugging aids Peter Feiner
2016-03-03  1:09   ` [kvm-unit-tests v2 1/8] x86: emulator: asm fixes Peter Feiner
2016-03-03  1:09   ` [kvm-unit-tests v2 2/8] x86: emulator: disable test_lldt Peter Feiner
2016-03-03  1:09   ` [kvm-unit-tests v2 3/8] x86: realmode: fix test_sgdt_sidt overflow Peter Feiner
2016-03-03  1:09   ` [kvm-unit-tests v2 4/8] x86: eventinj: make test work with -O0 Peter Feiner
2016-03-03 12:53     ` Paolo Bonzini
2016-03-03  1:09   ` [kvm-unit-tests v2 5/8] lib: backtrace printing Peter Feiner
2016-03-03  9:17     ` Andrew Jones
2016-03-03 17:01       ` Peter Feiner
2016-03-03 17:56         ` Andrew Jones
2016-03-03  1:09   ` [kvm-unit-tests v2 6/8] x86: lib: debug dump on unhandled exceptions Peter Feiner
2016-03-03  1:09   ` [kvm-unit-tests v2 7/8] lib: dump stack on abort() Peter Feiner
2016-03-03  9:19     ` Andrew Jones
2016-03-03  1:09   ` [kvm-unit-tests v2 8/8] scripts: pretty print stack traces Peter Feiner
2016-03-03  9:54     ` Andrew Jones
2016-03-03 12:58   ` [kvm-unit-tests v2 0/8] Debugging aids Paolo Bonzini
2016-03-03 20:48 ` [kvm-unit-tests v3 0/4] " Peter Feiner
2016-03-03 20:48   ` [kvm-unit-tests v3 1/4] lib: backtrace printing Peter Feiner
2016-03-04 10:15     ` Andrew Jones
2016-03-03 20:48   ` [kvm-unit-tests v3 2/4] x86: lib: debug dump on unhandled exceptions Peter Feiner
2016-03-03 20:48   ` [kvm-unit-tests v3 3/4] lib: dump stack on failed assert() Peter Feiner
2016-03-04 10:25     ` Andrew Jones
2016-03-03 20:48   ` [kvm-unit-tests v3 4/4] scripts: pretty print stack traces Peter Feiner
2016-03-04 10:24     ` Andrew Jones
2016-03-04 16:55       ` Peter Feiner
2016-03-04 18:43         ` Andrew Jones
2016-03-04 19:33 ` [PATCH kvm-unit-tests v4 0/6] Debugging aids Peter Feiner
2016-03-04 19:33   ` [PATCH kvm-unit-tests v4 1/5] lib: backtrace printing Peter Feiner
2016-03-04 19:33   ` [PATCH kvm-unit-tests v4 2/5] x86: lib: debug dump on unhandled exceptions Peter Feiner
2016-03-04 19:33   ` [PATCH kvm-unit-tests v4 3/5] lib: dump stack on failed assert() Peter Feiner
2016-03-04 19:34   ` [PATCH kvm-unit-tests v4 4/5] scripts: pretty print stack traces Peter Feiner
2016-03-04 19:34   ` [PATCH kvm-unit-tests v4 5/5] scripts: automatically pretty print stacks Peter Feiner
2016-03-05 11:29     ` Andrew Jones
2016-03-07 17:48       ` Peter Feiner
2016-03-04 19:37   ` [PATCH kvm-unit-tests v4 0/6] Debugging aids Peter Feiner
2016-03-07 17:46 ` [PATCH kvm-unit-tests v5 0/5] " Peter Feiner
2016-03-07 17:46   ` [PATCH kvm-unit-tests v5 1/5] lib: backtrace printing Peter Feiner
2016-03-08  4:24     ` Andrew Jones [this message]
2016-03-11  0:31       ` Peter Feiner
2016-03-07 17:46   ` [PATCH kvm-unit-tests v5 2/5] x86: lib: debug dump on unhandled exceptions Peter Feiner
2016-03-07 17:46   ` [PATCH kvm-unit-tests v5 3/5] lib: dump stack on failed assert() Peter Feiner
2016-03-07 17:46   ` [PATCH kvm-unit-tests v5 4/5] scripts: pretty print stack traces Peter Feiner
2016-03-07 17:46   ` [PATCH kvm-unit-tests v5 5/5] scripts: automatically pretty print stacks Peter Feiner
2016-03-08  4:31   ` [PATCH kvm-unit-tests v5 0/5] Debugging aids Andrew Jones
2016-03-11  0:47 ` [PATCH kvm-unit-tests v6 " Peter Feiner
2016-03-11  0:47   ` [PATCH kvm-unit-tests v6 1/5] lib: backtrace printing Peter Feiner
2016-03-11  0:47   ` [PATCH kvm-unit-tests v6 2/5] x86: lib: debug dump on unhandled exceptions Peter Feiner
2016-03-11  0:47   ` [PATCH kvm-unit-tests v6 3/5] lib: dump stack on failed assert() Peter Feiner
2016-03-11  0:47   ` [PATCH kvm-unit-tests v6 4/5] scripts: pretty print stack traces Peter Feiner
2016-03-11  0:47   ` [PATCH kvm-unit-tests v6 5/5] scripts: automatically pretty print stacks Peter Feiner
2016-03-11  2:41   ` [PATCH kvm-unit-tests v6 0/5] Debugging aids Andrew Jones

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160308042325.GB1638@localhost.redhat.com \
    --to=drjones@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=pfeiner@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.