You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2026/09/09 02:21:29 UTC

(nuttx) branch master updated (a60ee84197b -> 69061ea2466)

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

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


    from a60ee84197b arch/arm/src/common/stm32: accept interface-recipient GET/SET_DESCRIPTOR
     new 4cdd3cdbda4 arch/arm, libs/libc/elf: Build FDPIC modules in the normal ELF build.
     new 77f263b4fa3 cmake: Build FDPIC modules the way the make build does.
     new 69061ea2466 arch/arm: Say which linker is missing when FDPIC has none.

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 arch/arm/src/cmake/elf.cmake       | 58 +++++++++++++++++++++++++++++-----
 arch/arm/src/common/Toolchain.defs | 34 ++++++++++++++++++++
 cmake/nuttx_add_application.cmake  | 12 +++++--
 libs/libc/elf/gnu-elf.ld.in        | 64 +++++++++++++++++++++++++++++++-------
 4 files changed, 147 insertions(+), 21 deletions(-)


(nuttx) 01/03: arch/arm, libs/libc/elf: Build FDPIC modules in the normal ELF build.

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 4cdd3cdbda47867c66971fdf0ebe6bcc3e75c5f1
Author: Marco Casaroli <ma...@gmail.com>
AuthorDate: Fri Aug 28 18:22:08 2026 +0200

    arch/arm, libs/libc/elf: Build FDPIC modules in the normal ELF build.
    
    With CONFIG_FDPIC selected, a module built by apps/Application.mk is now an
    FDPIC shared object.  Nothing about how a module is written or built
    changes: the same MODULE = m in the same Makefile, the same crt0 and the
    same linker script.
    
    Two things differ from the position independent build beside it.  The
    compiler is told -mfdpic -fPIC, and the link is done by an
    arm-uclinuxfdpiceabi linker.  The stock arm-none-eabi compiler emits correct
    FDPIC objects for both C and C++, so only the link needs it: the stock
    linker carries the armelf emulation alone and would turn every import into
    an R_ARM_JUMP_SLOT, one word, where the ABI wants an R_ARM_FUNCDESC_VALUE,
    which is two, a code address and the data base that goes with it.  Such a
    module links cleanly and then calls out of itself with the caller's data
    base still in r9.  That linker is in the CI image.
    
    gnu-elf.ld.in gains the two segments an FDPIC module needs, under
    CONFIG_FDPIC, because the loader places its read-only and writable segments
    independently, and names .dynamic, because a shared object is bound through
    it.  The sections themselves are untouched and so are the symbols crt0.c
    walks, so one script serves both and both build systems get it.
    
    .bss moves to the end of the script, for every configuration and not only
    FDPIC.  It held no file content but sat ahead of .got and .dynamic, which
    do, so the writable segment's p_filesz had to span it and the module file
    carried the whole of .bss.  A module with 16 KiB of .bss went from 26724 to
    10340 bytes, and its writable segment from p_filesz 0x40ac to 0xac against
    an unchanged p_memsz.  The loader reads p_filesz off the media, so it read
    those bytes too.
    
    Built for mps3-an547:picostest with apps/examples/elf, CONFIG_FDPIC both
    ways.  With it on, every module in apps/bin is ARM FDPIC with two PT_LOAD
    segments and enters at _start; hello++3, which has a static C++ object,
    carries DT_INIT_ARRAY and DT_FINI_ARRAY.  With it off the generated script
    has no PHDRS and the modules are what they were.
    
    Assisted-by: Claude Opus 5 (1M context) <no...@anthropic.com>
    Signed-off-by: Marco Casaroli <ma...@gmail.com>
---
 arch/arm/src/common/Toolchain.defs | 18 +++++++++++
 libs/libc/elf/gnu-elf.ld.in        | 64 +++++++++++++++++++++++++++++++-------
 2 files changed, 71 insertions(+), 11 deletions(-)

diff --git a/arch/arm/src/common/Toolchain.defs b/arch/arm/src/common/Toolchain.defs
index 155ef3f3d7c..949b7161573 100644
--- a/arch/arm/src/common/Toolchain.defs
+++ b/arch/arm/src/common/Toolchain.defs
@@ -642,11 +642,29 @@ ifeq ($(CONFIG_PIC),y)
   # after including this file, which would discard the flag.
 
   ARCHCFLAGS += --fixed-r9
+
+ifeq ($(CONFIG_FDPIC),y)
+  # An FDPIC module is a shared object whose two segments the loader places
+  # independently.  The stock compiler emits correct FDPIC objects for both C
+  # and C++, so only the link needs the arm-uclinuxfdpiceabi linker: the
+  # stock one carries the armelf emulation alone and would turn every import
+  # into a jump slot where the ABI wants a function descriptor.
+
+  FDPIC_CROSSDEV ?= arm-uclinuxfdpiceabi-
+  MODULELD = $(FDPIC_CROSSDEV)ld
+
+  CELFFLAGS += -mfdpic -fPIC -Wa,--noexecstack
+  CXXELFFLAGS += -mfdpic -fPIC -Wa,--noexecstack
+
+  LDELFFLAGS += -m armelf_linux_fdpiceabi -shared -z now
+else
   CELFFLAGS += $(PICFLAGS) -mpic-register=r9
   CXXELFFLAGS += $(PICFLAGS) -mpic-register=r9
 
   # Generate an executable elf, need to ignore undefined symbols
   LDELFFLAGS += --unresolved-symbols=ignore-in-object-files --emit-relocs
+endif
+
 else
   ifneq ($(CONFIG_BINFMT_ELF_EXECUTABLE),y)
     LDELFFLAGS += -r
diff --git a/libs/libc/elf/gnu-elf.ld.in b/libs/libc/elf/gnu-elf.ld.in
index 340a91df5a2..be0c8776050 100644
--- a/libs/libc/elf/gnu-elf.ld.in
+++ b/libs/libc/elf/gnu-elf.ld.in
@@ -39,6 +39,34 @@
 #  define SECTIONS_ALIGN 4
 #endif
 
+/* An FDPIC module is a shared object whose read-only and writable segments
+ * the loader places independently: the read-only one runs where the
+ * filesystem already holds it and only the writable one is copied to RAM,
+ * once per running instance.  So the two go into segments of their own, and
+ * .dynamic is named, because a shared object is bound through it.
+ *
+ * Everything else is common, the symbols crt0.c walks included, so a module
+ * is built and entered the same way whichever this is.
+ */
+
+#ifdef CONFIG_FDPIC
+#  define PHDR_TEXT :text
+#  define PHDR_DATA :data
+#  define DATA_ALIGN . = ALIGN(0x1000);
+
+PHDRS
+{
+  text    PT_LOAD FLAGS(5);    /* Read and execute */
+  data    PT_LOAD FLAGS(6);    /* Read and write   */
+  dynamic PT_DYNAMIC FLAGS(6);
+}
+
+#else
+#  define PHDR_TEXT
+#  define PHDR_DATA
+#  define DATA_ALIGN
+#endif
+
 SECTIONS
 {
   .text TEXT :
@@ -53,7 +81,7 @@ SECTIONS
       *(.jcr)
       . = ALIGN(SECTIONS_ALIGN);
       _etext = . ;
-    }
+    } PHDR_TEXT
 
   .rodata :
     {
@@ -64,7 +92,9 @@ SECTIONS
       *(.gnu.linkonce.r*)
       . = ALIGN(SECTIONS_ALIGN);
       _erodata = . ;
-    }
+    } PHDR_TEXT
+
+  DATA_ALIGN
 
   .data DATA :
     {
@@ -75,7 +105,7 @@ SECTIONS
       *(.gnu.linkonce.d*)
       . = ALIGN(SECTIONS_ALIGN);
       _edata = . ;
-    }
+    } PHDR_DATA
 
   .init_array :
     {
@@ -86,7 +116,7 @@ SECTIONS
       . = ALIGN(SECTIONS_ALIGN);
       _einit = .;
       _ectors = .;
-    }
+    } PHDR_DATA
 
   .fini_array :
     {
@@ -98,7 +128,24 @@ SECTIONS
       . = ALIGN(SECTIONS_ALIGN);
       _efini = .;
       _edtors = .;
-    }
+    } PHDR_DATA
+
+#ifdef CONFIG_FDPIC
+  .dynamic :
+    {
+      *(.dynamic)
+    } :data :dynamic
+#endif
+
+  .got :
+    {
+      *(.got*)
+    } PHDR_DATA
+
+  /* .bss holds no file content, so it comes last.  Everything ahead of it
+   * has content, thus the writable segment's p_filesz stops where .bss
+   * starts and the file does not carry it.
+   */
 
   .bss :
     {
@@ -111,12 +158,7 @@ SECTIONS
       *(COMMON)
       . = ALIGN(SECTIONS_ALIGN);
       _ebss = . ;
-    }
-
-  .got :
-    {
-      *(.got*)
-    }
+    } PHDR_DATA
 
     /* Stabs debugging sections.    */
 


(nuttx) 03/03: arch/arm: Say which linker is missing when FDPIC has none.

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 69061ea24662e86f94c4b4db45d4c354ddff08f6
Author: Marco Casaroli <ma...@gmail.com>
AuthorDate: Fri Aug 28 18:42:26 2026 +0200

    arch/arm: Say which linker is missing when FDPIC has none.
    
    Without this the build says "arm-uclinuxfdpiceabi-ld: Command not found",
    which does not say what that is, where to get it, or that the prefix can be
    changed.
    
    The make build reports at the link rather than while parsing, so that a tree
    configured for FDPIC on a host without the linker can still be cleaned and
    reconfigured: an error at parse time takes make distclean with it.  The
    cmake build reports while configuring, where nothing is built yet.
    
    Both name FDPIC_CROSSDEV, so a linker under another prefix can be used.
    
    Checked on mps3-an547:picostest with CONFIG_FDPIC and the linker off PATH:
    make distclean succeeds, and a module link stops with the message.  With the
    linker present the modules build as before.
    
    Signed-off-by: Marco Casaroli <ma...@gmail.com>
---
 arch/arm/src/cmake/elf.cmake       | 15 ++++++++++++++-
 arch/arm/src/common/Toolchain.defs | 16 ++++++++++++++++
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/arch/arm/src/cmake/elf.cmake b/arch/arm/src/cmake/elf.cmake
index 91b1037d631..ab09828847c 100644
--- a/arch/arm/src/cmake/elf.cmake
+++ b/arch/arm/src/cmake/elf.cmake
@@ -39,8 +39,21 @@ if(CONFIG_FDPIC)
     set(FDPIC_CROSSDEV arm-uclinuxfdpiceabi-)
   endif()
 
+  # Say which linker is missing rather than failing later with a command that
+  # cannot be run.
+
+  find_program(FDPIC_LD "${FDPIC_CROSSDEV}ld")
+
+  if(NOT FDPIC_LD)
+    message(
+      FATAL_ERROR
+        "CONFIG_FDPIC needs ${FDPIC_CROSSDEV}ld, which is not on PATH. "
+        "It is in the NuttX CI image, and tools/ci/docker/linux/Dockerfile "
+        "shows how it is built.  Set FDPIC_CROSSDEV to use a different prefix")
+  endif()
+
   set(CMAKE_ELF_LD
-      "${FDPIC_CROSSDEV}ld"
+      "${FDPIC_LD}"
       CACHE INTERNAL "Linker for FDPIC modules")
 
   nuttx_elf_compile_options(-mfdpic -fPIC -Wa,--noexecstack)
diff --git a/arch/arm/src/common/Toolchain.defs b/arch/arm/src/common/Toolchain.defs
index 949b7161573..a1d65803263 100644
--- a/arch/arm/src/common/Toolchain.defs
+++ b/arch/arm/src/common/Toolchain.defs
@@ -653,6 +653,22 @@ ifeq ($(CONFIG_FDPIC),y)
   FDPIC_CROSSDEV ?= arm-uclinuxfdpiceabi-
   MODULELD = $(FDPIC_CROSSDEV)ld
 
+  # Say which linker is missing rather than letting make report a command it
+  # cannot run.  The report is deferred to the link itself rather than made
+  # here, so that a tree configured for FDPIC on a host without the linker can
+  # still be cleaned and reconfigured.
+
+  FDPIC_LD_FOUND := $(shell command -v $(MODULELD) 2> /dev/null)
+
+  ifeq ($(FDPIC_LD_FOUND),)
+    FDPIC_NO_LD_MSG = CONFIG_FDPIC needs $(FDPIC_CROSSDEV)ld, which is not \
+      on PATH.  It is in the NuttX CI image, and \
+      tools/ci/docker/linux/Dockerfile shows how it is built.  Set \
+      FDPIC_CROSSDEV to use a different prefix.
+
+    MODULELD = $(SHELL) -c 'echo "ERROR: $(FDPIC_NO_LD_MSG)" 1>&2; exit 1' --
+  endif
+
   CELFFLAGS += -mfdpic -fPIC -Wa,--noexecstack
   CXXELFFLAGS += -mfdpic -fPIC -Wa,--noexecstack
 


(nuttx) 02/03: cmake: Build FDPIC modules the way the make build does.

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 77f263b4fa3096d488dc12f9e098e29aff3f8687
Author: Marco Casaroli <ma...@gmail.com>
AuthorDate: Fri Aug 28 18:35:28 2026 +0200

    cmake: Build FDPIC modules the way the make build does.
    
    The same two differences as in common/Toolchain.defs: the compiler is told
    -mfdpic -fPIC, and the module link is done by an arm-uclinuxfdpiceabi
    linker.
    
    That linker is not the one that links the firmware, so the module link needs
    a variable of its own.  CMAKE_ELF_LD is the ordinary linker unless the
    architecture sets it, which arm does under CONFIG_FDPIC.
    
    The linker script needs nothing here: it is generated from
    libs/libc/elf/gnu-elf.ld.in, which both build systems preprocess, and the
    FDPIC segments are already in it.
    
    -r is now conditional on CONFIG_PIC being off, which is what
    common/Toolchain.defs has always done and the cmake build did not: a
    position independent module is linked as an executable, and an FDPIC one as
    a shared object, so neither wants it.
    
    -fno-use-cxa-atexit mirrors CXXELFFLAGS for the same reason it was added
    there.
    
    Configured and built mps3-an547:picostest with CONFIG_FDPIC through cmake and
    ninja: the modules in bin/ are ARM FDPIC with two PT_LOAD segments.
    
    Signed-off-by: Marco Casaroli <ma...@gmail.com>
---
 arch/arm/src/cmake/elf.cmake      | 45 ++++++++++++++++++++++++++++++++-------
 cmake/nuttx_add_application.cmake | 12 +++++++++--
 2 files changed, 47 insertions(+), 10 deletions(-)

diff --git a/arch/arm/src/cmake/elf.cmake b/arch/arm/src/cmake/elf.cmake
index 7108aa4c174..91b1037d631 100644
--- a/arch/arm/src/cmake/elf.cmake
+++ b/arch/arm/src/cmake/elf.cmake
@@ -27,17 +27,46 @@ nuttx_mod_compile_options(-fvisibility=hidden -mlong-calls)
 nuttx_elf_compile_options_ifdef(CONFIG_UNWINDER_ARM -fno-unwind-tables
                                 -fno-asynchronous-unwind-tables)
 
-# An ELF module needs r9 as its PIC base, so it must not also have the register
-# fixed: GCC rejects that pair with "unable to use 'r9' for PIC register".  This
-# mirrors CELFFLAGS in common/Toolchain.defs, which filters --fixed-r9 back out
-# of the inherited CFLAGS for the same reason.
+if(CONFIG_FDPIC)
 
-nuttx_elf_compile_options_ifdef(CONFIG_PIC -mpic-register=r9)
+  # An FDPIC module is a shared object whose two segments the loader places
+  # independently.  The stock compiler emits correct FDPIC objects for both C
+  # and C++, so only the link needs the arm-uclinuxfdpiceabi linker: the stock
+  # one carries the armelf emulation alone and would turn every import into a
+  # jump slot where the ABI wants a function descriptor.
 
-nuttx_elf_link_options_ifdef(
-  CONFIG_PIC --unresolved-symbols=ignore-in-object-files --emit-relocs)
+  if(NOT FDPIC_CROSSDEV)
+    set(FDPIC_CROSSDEV arm-uclinuxfdpiceabi-)
+  endif()
+
+  set(CMAKE_ELF_LD
+      "${FDPIC_CROSSDEV}ld"
+      CACHE INTERNAL "Linker for FDPIC modules")
+
+  nuttx_elf_compile_options(-mfdpic -fPIC -Wa,--noexecstack)
+
+  nuttx_elf_link_options(-m armelf_linux_fdpiceabi -shared -z now)
+
+elseif(CONFIG_PIC)
+
+  # An ELF module needs r9 as its PIC base, so it must not also have the
+  # register fixed: GCC rejects that pair with "unable to use 'r9' for PIC
+  # register".  This mirrors CELFFLAGS in common/Toolchain.defs, which filters
+  # --fixed-r9 back out of the inherited CFLAGS for the same reason.
 
-nuttx_elf_link_options_ifdef(CONFIG_BINFMT_ELF_RELOCATABLE -r)
+  nuttx_elf_compile_options(-mpic-register=r9)
+
+  nuttx_elf_link_options(--unresolved-symbols=ignore-in-object-files
+                         --emit-relocs)
+
+endif()
+
+# Not with CONFIG_PIC: there the module is linked as an executable, which is
+# what common/Toolchain.defs does too.
+
+if(CONFIG_BINFMT_ELF_RELOCATABLE AND NOT CONFIG_PIC)
+  nuttx_elf_link_options(-r)
+endif()
 
 nuttx_mod_link_options(-r)
 
diff --git a/cmake/nuttx_add_application.cmake b/cmake/nuttx_add_application.cmake
index 4864eaedbd6..bf4b626ce93 100644
--- a/cmake/nuttx_add_application.cmake
+++ b/cmake/nuttx_add_application.cmake
@@ -149,7 +149,15 @@ function(nuttx_add_application)
         if(TARGET STARTUP_OBJS)
           add_dependencies(${TARGET} STARTUP_OBJS)
         endif()
-        if(NOT "${CMAKE_LD}" MATCHES "gcc$")
+        # A module may need a different linker from the one that links the
+        # firmware: an FDPIC module does, because the stock linker cannot
+        # produce one.  CMAKE_ELF_LD is that linker, and it is the ordinary one
+        # unless the architecture says otherwise.
+
+        if(NOT CMAKE_ELF_LD)
+          set(CMAKE_ELF_LD ${CMAKE_LD})
+        endif()
+        if(NOT "${CMAKE_ELF_LD}" MATCHES "gcc$")
           set(USE_LINKER True)
         endif()
         if(STACKSIZE)
@@ -179,7 +187,7 @@ function(nuttx_add_application)
           POST_BUILD
           COMMAND
             # add default link option
-            ${CMAKE_LD} -T ${NUTTX_BINARY_DIR}/gnu-elf.ld
+            ${CMAKE_ELF_LD} -T ${NUTTX_BINARY_DIR}/gnu-elf.ld
             # add global MOD link option if dynlib link
             $<$<BOOL:${DYNLIB_ELF_MODE}>:$<TARGET_PROPERTY:nuttx_global,NUTTX_MOD_APP_LINK_OPTIONS>>
             # add global ELF link option if m&kernel link