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. - CELFFLAGS += -mfdpic -fPIC -Wa,--noexecstack -Wa,--fdpic - CXXELFFLAGS += -mfdpic -fPIC -Wa,--noexecstack -Wa,--fdpic + FDPICFLAGS = -mfdpic -fPIC -Wa,--noexecstack -Wa,--fdpic \ + -fno-optimize-sibling-calls + + 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)