nuttx: PolarFire SoC - C++ Exception Exits Before Catch

Summary

On the PolarFire Icicle board, when building from master with a config based on icicle:nsh (plus config and flag changes detailed below), the cxxtest built-in app exception test fails. It throws the exception and then exits without catching the exception.

I’ve tried this on both the Icicle board and a PolarFire Renode simulation. I’m building with riscv-none-elf-* from xPack: gcc version 13.2.0 (xPack GNU RISC-V Embedded GCC x86_64).

I’m hoping someone knows what the issue might be as I’m not familiar with the behind the scenes of exception handling. Meanwhile I’ll keep working on this.

Config

Changed optimization to -Og for debugging and set -mstrict-align to prevent a crash due to misaligned instructions.

Ran make savedefconfig and the following. The task size configs are set because I had to increase CONFIG_DEFAULT_TASK_STACKSIZE to prevent a stack overflow during exception unwinding.

$ diff boards/risc-v/mpfs/icicle/configs/nsh/defconfig  defconfig
9a10,12
> # CONFIG_NSH_DISABLE_MB is not set
> # CONFIG_NSH_DISABLE_MH is not set
> # CONFIG_NSH_DISABLE_MW is not set
21a25,26
> CONFIG_CXX_EXCEPTION=y
> CONFIG_CXX_RTTI=y
25a31
> CONFIG_DEFAULT_TASK_STACKSIZE=32768
30a37
> CONFIG_HAVE_CXX=y
34a42,43
> CONFIG_LIBCXX=y
> CONFIG_LIBCXXABI=y
37a47
> CONFIG_LIBM=y
50a61
> CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE=2048
51a63
> CONFIG_PTHREAD_STACK_DEFAULT=2048
58a71
> CONFIG_SCHED_HPWORKSTACKSIZE=2048
59a73
> CONFIG_SCHED_LPWORKSTACKSIZE=2048
66a81
> CONFIG_SYSTEM_NSH_STACKSIZE=2048
68a84
> CONFIG_TESTING_CXXTEST=y
69a86
> CONFIG_TESTING_GETPRIME_STACKSIZE=2048
70a88,89
> CONFIG_TESTING_OSTEST_FPUSTACKSIZE=2048
> CONFIG_TLS_NELEM=4

About this issue

  • Original URL
  • State: open
  • Created 4 months ago
  • Comments: 17 (9 by maintainers)

Most upvoted comments

I don’t use exceptions so no idea what’s going on

I made some progress on this today. _Unwind_Find_FDE was returning NULL because the unseen_objects linked list wasn’t initialized. This linked list needs to be initialized at startup, and then during exception handling it has nodes added and moved into seen_objects. The list is used for finding an FDE by program counter.

Looks like users of libgcc can either link with crtbegin.o or write their own calls to libgcc __register_frame_info* function. The crtstuff.c file provides a frame_dummy() function which is supposed to be placed in the .init_array section by the linker, so that it gets invoked by the initialization logic pre-main. This frame_dummy function does the registration using __EH_FRAME_BEGIN__. The function was getting called by NuttX lib_cxx_initialize() but, __EH_FRAME_BEGIN__ was NULL so initialization didn’t happen.

I hacked up the Toolchain.defs file to link crtbegin.o and crtend.o so that I get frame_dummy. With a new .eh_frame section in the linker script, __EH_FRAME_BEGIN__ points to the beginning of .eh_frame and initialization works.

image

image

The next problem is that during libgcc FDE searching, I get a RISC-V load address misaligned crash. I’m not sure what to do about this yet.

Hi @sastel that is very interesting investigation. If you can, please write down about it in some blog, probably it will help more people in the future.

@sastel maybe you can look some other board with C++ support to trace the differences, probably there some other details. Also if you could try in some ARM (like STM32F4Discovery board) it could help to see if everything still working as expected.