This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit ebabdd57f3bd8a98fb4c5091319b907522445a8a
Author: Marco Casaroli <[email protected]>
AuthorDate: Wed Oct 7 08:09:50 2026 +0200

    arch/arm: Keep GCC from making tail calls in an FDPIC module.
    
    With -mfdpic and -mlong-calls, GCC turns a call to an imported function
    in tail position into "ldr r3, [r9, #off]; bx r3".  The GOT slot holds
    the address of the function descriptor, so the branch goes to the
    descriptor in RAM instead of through it, and the core faults.  A normal
    call loads the code address and the data base from the descriptor
    first.  GCC 13.2 and 15.3 both do this.
    
    Only an optimized build makes tail calls.  The C++ library of
    apps/testing/fs/xipfs then faults in its constructor, which ends in a
    call to syslog(), and the test stops at "stage the C++ module".
    
    Pass -fno-optimize-sibling-calls with the other FDPIC flags, in the make
    build and the CMake build.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 arch/arm/src/cmake/elf.cmake       | 11 +++++++++--
 arch/arm/src/common/Toolchain.defs | 15 +++++++++++----
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/arch/arm/src/cmake/elf.cmake b/arch/arm/src/cmake/elf.cmake
index 465f442ae3f..45fb444a814 100644
--- a/arch/arm/src/cmake/elf.cmake
+++ b/arch/arm/src/cmake/elf.cmake
@@ -58,15 +58,22 @@ if(CONFIG_FDPIC)
 
   # GCC before 14 does not pass --fdpic to the assembler for -mfdpic, and the
   # assembler then rejects the FDPIC relocations, so pass it here.
+  #
+  # With -mlong-calls, GCC turns a call in tail position into a branch to the
+  # function descriptor rather than through it, which faults.  Keep it from
+  # making tail calls.
 
-  nuttx_elf_compile_options(-mfdpic -fPIC -Wa,--noexecstack -Wa,--fdpic)
+  set(FDPIC_FLAGS -mfdpic -fPIC -Wa,--noexecstack -Wa,--fdpic
+                  -fno-optimize-sibling-calls)
+
+  nuttx_elf_compile_options(${FDPIC_FLAGS})
 
   nuttx_elf_link_options(-m armelf_linux_fdpiceabi -shared -z now)
 
   # A shared library is an FDPIC shared object too, as LDMODULEFLAGS makes it 
in
   # common/Toolchain.defs
 
-  nuttx_mod_compile_options(-mfdpic -fPIC -Wa,--noexecstack -Wa,--fdpic)
+  nuttx_mod_compile_options(${FDPIC_FLAGS})
 
   nuttx_mod_link_options(-m armelf_linux_fdpiceabi -shared -z now)
 
diff --git a/arch/arm/src/common/Toolchain.defs 
b/arch/arm/src/common/Toolchain.defs
index d681cd17278..787e048fcd9 100644
--- a/arch/arm/src/common/Toolchain.defs
+++ b/arch/arm/src/common/Toolchain.defs
@@ -686,9 +686,16 @@ ifeq ($(CONFIG_FDPIC),y)
 
   # GCC before 14 does not pass --fdpic to the assembler for -mfdpic, and the
   # assembler then rejects the FDPIC relocations, so pass it here.
+  #
+  # With -mlong-calls, GCC turns a call in tail position into a branch to the
+  # function descriptor rather than through it, which faults.  Keep it from
+  # making tail calls.
+
+  FDPICFLAGS = -mfdpic -fPIC -Wa,--noexecstack -Wa,--fdpic \
+               -fno-optimize-sibling-calls
 
-  CELFFLAGS += -mfdpic -fPIC -Wa,--noexecstack -Wa,--fdpic
-  CXXELFFLAGS += -mfdpic -fPIC -Wa,--noexecstack -Wa,--fdpic
+  CELFFLAGS += $(FDPICFLAGS)
+  CXXELFFLAGS += $(FDPICFLAGS)
 
   LDELFFLAGS += -m armelf_linux_fdpiceabi -shared -z now
 
@@ -700,8 +707,8 @@ ifeq ($(CONFIG_FDPIC),y)
   # The entry point is left to the caller:  a module is entered at _start,
   # a library is only called into.
 
-  CMODULEFLAGS += -mfdpic -fPIC -Wa,--noexecstack -Wa,--fdpic
-  CXXMODULEFLAGS += -mfdpic -fPIC -Wa,--noexecstack -Wa,--fdpic
+  CMODULEFLAGS += $(FDPICFLAGS)
+  CXXMODULEFLAGS += $(FDPICFLAGS)
 
   LDMODULEFLAGS = -m armelf_linux_fdpiceabi -shared -z now \
                   -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/elf/gnu-elf.ld)

Reply via email to