LingaoM opened a new pull request, #19882:
URL: https://github.com/apache/nuttx/pull/19882
Loadable ELF tasks currently do not run module init/fini arrays when they
are executed through the binfmt path. This is enough for many C modules, but
C++ modules rely on those arrays for global constructors and destructors, so
objects with static storage duration are not initialized or finalized correctly.
C++ exceptions on the x86_64 SIM target also need the module DWARF unwind
data to be visible to the host unwinder. The loaded .eh_frame section is
relocated by the ELF loader, but it is not registered with libgcc unwinder
state, so stack unwinding through a loaded module cannot find the FDEs needed
for C++ catch handling.
Run loadable ELF init arrays from nxtask_startup() before entering the task
main function and run fini arrays when the task returns or exits. The fini
array count is cleared before callbacks are invoked so the same module
destructors are not called twice on normal return followed by binfmt unload.
Add an optional CONFIG_LIBC_ELF_EH_FRAME path for x86_64 SIM that registers
a loaded module .eh_frame section after relocation and deregisters it on unload
or failed load cleanup. Keep the option disabled by default and limited to SIM,
where the host DWARF unwinder APIs are available.
Preserve .eh_frame and .gcc_except_table in the loadable ELF linker script
so exception metadata remains available after module linking. Also accept
R_X86_64_NONE as a no-op relocation in the SIM x86_64 relocator; some C++
objects can contain those entries and rejecting them prevents otherwise valid
modules from loading.
The apps-side loadelf demo and stress tests are carried in the companion
apps commit:
https://github.com/LingaoM/nuttx-apps/commit/1c75943922f5dfb3818ddb8594c9d3f1a0b9bd87
Testing:
Host:
Ubuntu 22.04 x86_64
Board/config:
apps-side sim/loadelfdemo
Apps test code:
https://github.com/LingaoM/nuttx-apps/commit/1c75943922f5dfb3818ddb8594c9d3f1a0b9bd87
Configuration highlights:
CONFIG_ELF=y
CONFIG_LIBC_EXECFUNCS=y
CONFIG_EXECFUNCS_HAVE_SYMTAB=y
# CONFIG_EXECFUNCS_SYSTEM_SYMTAB is not set
CONFIG_BINFMT_CONSTRUCTORS=y
CONFIG_CXX_EXCEPTION=y
CONFIG_CXX_RTTI=y
CONFIG_CXX_WCHAR=y
CONFIG_LIBC_ELF_EH_FRAME=y
CONFIG_LIBCXXNONE=y
CONFIG_LIBMINIABI=y
CONFIG_SIM_TOOLCHAIN_GCC=y
Build and export:
make distclean
./tools/configure.sh -l ../nuttx-apps/sim/loadelfdemo
make olddefconfig KCONFIG_OLDDEFCONFIG="python3 -m olddefconfig"
make -j16
make export
External ELF samples built from the NuttX export:
make -C ../nuttx-apps/examples/loadelfdemo/samples/loadelf_sample \
clean install check
make -C ../nuttx-apps/examples/loadelfdemo/samples/loadelf_cpp_stress \
clean install check
Runtime test:
printf 'loadelfdemo loadelf_sample 10 20 30\n\
loadelfdemo loadelf_sample 1 2\n\
loadelfdemo loadelf_cpp_stress\n\
poweroff\n' | timeout 80s ./nuttx
Observed result:
loadelf_sample loaded successfully twice, with the second run reusing the
existing /system/bin mount. loadelf_cpp_stress passed all checks
including
global constructors, STL containers, RTTI, exceptions, iostream, regex,
filesystem, thread/condition_variable, future/async, and global
destructor
execution.
<img width="1634" height="1638" alt="image"
src="https://github.com/user-attachments/assets/ebc05130-e04e-4bb7-8901-7533805a95ed"
/>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]