[PATCH] riscv: add backtrace support

Ben Dooks ben.dooks at codethink.co.uk
Thu May 25 13:05:15 CEST 2023


On 15/05/2023 14:03, Ben Dooks wrote:
> When debugging, it is useful to have a backtrace to find
> out what is in the call stack as the previous function (RA)
> may not have been the culprit.
> 
> Since this adds size to the build, do not add it by default
> and avoid putting it in the SPL build if not needed.

Hi, has anyone had time to review this?

As a note, my sifive.com address may go soon, so please
add ben.dooks at codethink.co.uk to any followups.

> Signed-off-by: Ben Dooks <ben.dooks at sifive.com>
> ---
>   arch/riscv/Kconfig          | 10 ++++++++++
>   arch/riscv/Makefile         |  4 ++++
>   arch/riscv/cpu/start.S      |  1 +
>   arch/riscv/lib/interrupts.c | 35 +++++++++++++++++++++++++++++++++++
>   4 files changed, 50 insertions(+)
> 
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index f6ed05906a..3f2316cfb5 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -98,6 +98,16 @@ config ARCH_RV64I
>   
>   endchoice
>   
> +config FRAMEPOINTER
> +	bool "Build with frame pointer for stack unwinding"
> +	help
> +	  Choose this option to use the frame pointer so the stack can be
> +	  unwound if needed. This is useful for tracing where faults came
> +	  from as the source may be several functions back
> +
> +	  If you say Y here, then the code size will be increased due to
> +	  having to store the fp.
> +
>   choice
>   	prompt "Code Model"
>   	default CMODEL_MEDLOW
> diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
> index 4963b5109b..0cb60c7c7e 100644
> --- a/arch/riscv/Makefile
> +++ b/arch/riscv/Makefile
> @@ -45,6 +45,10 @@ endif
>   ARCH_FLAGS = -march=$(RISCV_MARCH) -mabi=$(ABI) \
>   	     -mcmodel=$(CMODEL)
>   
> +ifeq ($(CONFIG_$(SPL_)FRAMEPOINTER),y)
> +	ARCH_FLAGS += -fno-omit-frame-pointer
> +endif
> +
>   PLATFORM_CPPFLAGS	+= $(ARCH_FLAGS)
>   CFLAGS_EFI		+= $(ARCH_FLAGS)
>   
> diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
> index dad22bfea8..3d13722615 100644
> --- a/arch/riscv/cpu/start.S
> +++ b/arch/riscv/cpu/start.S
> @@ -396,6 +396,7 @@ call_board_init_r:
>    */
>   	mv	a0, s3			/* gd_t */
>   	mv	a1, s4			/* dest_addr */
> +	mv	s0, zero		/* fp == NULL */
>   
>   /*
>    * jump to it ...
> diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c
> index e966afa7e3..db3d7e294b 100644
> --- a/arch/riscv/lib/interrupts.c
> +++ b/arch/riscv/lib/interrupts.c
> @@ -53,6 +53,40 @@ static void show_regs(struct pt_regs *regs)
>   #endif
>   }
>   
> +#if defined(CONFIG_FRAMEPOINTER) || defined(CONFIG_SPL_FRAMEPOINTER)
> +static void show_backtrace(struct pt_regs *regs)
> +{
> +	uintptr_t *fp = (uintptr_t *)regs->s0;
> +	unsigned count = 0;
> +	ulong ra;
> +
> +	printf("backtrace:\n");
> +
> +	/* there are a few entry points where the s0 register is
> +	 * set to gd, so to avoid changing those, just abort if
> +	 * the value is the same */
> +	while (fp != NULL && fp != (uintptr_t *)gd) {
> +		ra = fp[-1];
> +		printf("backtrace %2d: FP: " REG_FMT " RA: " REG_FMT,
> +		       count, (ulong)fp, ra);
> +
> +		if (gd && gd->flags & GD_FLG_RELOC)
> +			printf(" - RA: " REG_FMT " reloc adjusted\n",
> +			ra - gd->reloc_off);
> +		else
> +			printf("\n");
> +
> +		fp = (uintptr_t *)fp[-2];
> +		count++;
> +	}
> +}
> +#else
> +static void show_backtrace(struct pt_regs *regs)
> +{
> +	printf("No backtrace support enabled\n");
> +}
> +#endif
> +
>   /**
>    * instr_len() - get instruction length
>    *
> @@ -119,6 +153,7 @@ static void _exit_trap(ulong code, ulong epc, ulong tval, struct pt_regs *regs)
>   		       epc - gd->reloc_off, regs->ra - gd->reloc_off);
>   
>   	show_regs(regs);
> +	show_backtrace(regs);
>   	show_code(epc);
>   	show_efi_loaded_images(epc);
>   	panic("\n");

-- 
Ben Dooks				http://www.codethink.co.uk/
Senior Engineer				Codethink - Providing Genius

https://www.codethink.co.uk/privacy.html



More information about the U-Boot mailing list