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 21133a90c4e6f859ab1717825b6826f2674a914d Author: Marco Casaroli <[email protected]> AuthorDate: Mon Aug 3 13:37:32 2026 +0200 Documentation/nxflat: Document the in-tree mknxflat and the ABI marker. mknxflat is built from tools/nxflat by the NuttX build itself, so the toolchain section no longer sends the reader to buildroot for it; only ldnxflat still comes from there. Bring the mknxflat usage text in line with the tool, note that MKNXFLAT and LDNXFLAT are supplied by the ARM Toolchain.defs, and correct the r10 references left in the PIC descriptions. Describe the module ABI marker, so that a user whose prebuilt module starts failing exec() with ENOEXEC finds out that the loader refuses a module whose import table does not name __nxflat_abi_v2, and that rebuilding the module is the fix. Assisted-by: Claude Opus 5 (1M context) <[email protected]> Signed-off-by: Marco Casaroli <[email protected]> --- .../applications/examples/nxflatxip/index.rst | 6 +- Documentation/components/nxflat.rst | 119 +++++++++++++-------- .../rp23xx/boards/pimoroni-pico-2-plus/index.rst | 4 +- 3 files changed, 81 insertions(+), 48 deletions(-) diff --git a/Documentation/applications/examples/nxflatxip/index.rst b/Documentation/applications/examples/nxflatxip/index.rst index f3f2244d976..38e3e1c0732 100644 --- a/Documentation/applications/examples/nxflatxip/index.rst +++ b/Documentation/applications/examples/nxflatxip/index.rst @@ -61,9 +61,9 @@ Building the module =================== The module is built from ``module/xipmod.c`` at build time, exactly the way -:doc:`../nxflat/index` builds its test programs, so it needs the same two -host tools from the NuttX toolchain, ``mknxflat`` and ``ldnxflat``, and the -board's ``Make.defs`` must name them. +:doc:`../nxflat/index` builds its test programs, so it needs the same host +tools: ``mknxflat``, which NuttX builds itself, and ``ldnxflat``, which has +to come from the buildroot toolchain. See :doc:`/components/nxflat`. The module has no static data and no string constants, and reports through a callback into the firmware rather than formatting its own output. The comment diff --git a/Documentation/components/nxflat.rst b/Documentation/components/nxflat.rst index c7ff5de8bae..63c95a29796 100644 --- a/Documentation/components/nxflat.rst +++ b/Documentation/components/nxflat.rst @@ -88,8 +88,8 @@ Limitations - **Read-Only Data in RAM**: With older GCC compilers (at least up to 4.3.3), read-only data must reside in RAM. In code generated by GCC, all data references are - indexed by the PIC2 base register (that is usually R10 or sl for the - ARM processors). The includes read-only data (.rodata). Embedded + indexed by the PIC2 base register (r9 for the ARM processors). + The includes read-only data (.rodata). Embedded firmware developers normally like to keep .rodata in FLASH with the code sections. But because all data is referenced with the PIC base register, all of that data must lie in RAM. A NXFLAT @@ -136,35 +136,33 @@ such, NXFLAT is currently in an early alpha phase. NXFLAT Toolchain ================ -Building the NXFLAT Toolchain ------------------------------ - -In order to use NXFLAT, you must use special NXFLAT tools to create the -binary module in FLASH. To do this, you will need to download the -buildroot package and build it on your Linux or Cygwin machine. The -buildroot can be downloaded from -`Bitbucket.org <https://bitbucket.org/nuttx/buildroot/downloads>`__. You -will need version 0.1.7 or later. - -Here are some general build instructions: - -- You must have already configured NuttX in ``<some-dir>/nuttx`` -- Download the buildroot package ``buildroot-0.x.y`` into - ``<some-dir>`` -- Unpack ``<some-dir>/buildroot-0.x.y.tar.gz`` using a command like ``tar zxf buildroot-0.x.y``. - This will result in a new directory like ``<some-dir>/buildroot-0.x.y`` -- Move this into position: - ``mv <some-dir>/buildroot-0.x.y``\ <some-dir>/buildroot -- ``cd``\ <some-dir>/buildroot +Getting the NXFLAT Tools +------------------------ + +Building an NXFLAT module takes two tools beyond an ordinary GCC toolchain: +``mknxflat``, which generates the module's *thunk* file, and ``ldnxflat``, +which links the module into the NXFLAT binary format. + +``mknxflat`` is part of NuttX, in ``tools/nxflat``. The build produces it as +``tools/mknxflat`` whenever ``CONFIG_NXFLAT`` is selected, so there is +nothing to install. + +``ldnxflat`` is not part of NuttX and has to be built from the buildroot +package, which can be downloaded from +`Bitbucket.org <https://bitbucket.org/nuttx/buildroot/downloads>`__. You +will need version 0.1.7 or later: + +- Unpack the package and ``cd`` into the resulting directory. - Copy a configuration file into the top buildroot directory: ``cp boards/abc-defconfig-x.y.z .config``. -- Enable building of the NXFLAT tools by ``make menuconfig``. Select to - build the NXFLAT toolchain with GCC (you can also select omit - building GCC with and only build the NXFLAT toolchain for use with - your own GCC toolchain). -- Make the toolchain: ``make``. When the make completes, the tool - binaries will be available under - ``<some-dir>/buildroot/build_abc/staging_dir/bin`` +- Run ``make menuconfig`` and select the NXFLAT toolchain. Building GCC + can be omitted if you already have a toolchain of your own. +- Run ``make``. The tool binaries are left under + ``build_abc/staging_dir/bin``; put that directory on your ``PATH``. + +On ARM, ``arch/arm/src/common/Toolchain.defs`` provides both ``MKNXFLAT`` +(with the ``-a`` option following ``CONFIG_ARM_THUMB``) and ``LDNXFLAT``, so +a board only has to assign them if it needs something different. mknxflat -------- @@ -172,21 +170,27 @@ mknxflat ``mknxflat`` is used to build a *thunk* file. See below for usage:: - Usage: mknxflat [options] <bfd-filename> + Usage: mknxflat [options] <elf-filename> Where options are one or more of the following. Note - that a space is always required between the option and - any following arguments. + that a space is always required between the + option and any following arguments. + -a <arch> + Instruction set of the module: arm or thumb2 + [thumb2] -d Use dynamic symbol table. [symtab] - -f <cmd-filename> - Take next commands from <cmd-filename> [cmd-line] -o <out-filename> - Output to [stdout] + Output to <out-filename> [stdout] -v Verbose output [no output] -w Import weakly declared functions, i.e., weakly - declared functions are expected to be provided at - load-time [not imported] + declared functions are expected to be + provided at load-time [not imported] + +A module calls an imported function through one of these thunks, which +reaches the import table using the module's PIC base register. The thunks +are emitted as assembly, so ``-a`` must match the instruction set the module +was compiled for. ldnxflat -------- @@ -263,7 +267,7 @@ example). .. code-block:: makefile hello-thunk.S: hello.r1 - mknxflat -o $@ $^ + $(MKNXFLAT) -o $@ $^ * Target 3: @@ -277,7 +281,7 @@ example). .. code-block:: makefile hello: hello.r2 - ldnxflat -e main -s 2048 -o $@ $^ + $(LDNXFLAT) -e main -s 2048 -o $@ $^ **Target 1**. This target links all of the module's object files together into one relocatable object. Two relocatable objects will be @@ -331,6 +335,35 @@ object to create the final, NXFLAT module ``hello`` by executing **binfmt Registration** NXFLAT calls :c:func:`register_binfmt` to incorporate itself into the system. +Module ABI marker +----------------- + +The NXFLAT header carries no version field -- ``h_magic`` is written by +``ldnxflat``, which lives outside this repository and cannot be changed in +step with the loader -- so the module ABI is declared through the import +table instead. Every module built by ``mknxflat`` imports the symbol +``__nxflat_abi_v2``, the base firmware defines it, and the loader refuses a +module whose import table does not name it. The generation is bumped +whenever the module ABI changes; v2 is the move of the PIC base register to +r9, and a v1 module's thunks would add r10 and branch to a wild address on +the first call into the base firmware. + +A module built before the marker therefore fails ``exec()`` with +``ENOEXEC``, and with binfmt debug output enabled the loader reports:: + + ERROR: Module does not declare __nxflat_abi_v2: it was built by a + toolchain predating the r9 PIC base register. Rebuild it. + +Rebuilding the module with the current ``mknxflat`` is the entire fix; +nothing in the module source has to change. A module built against a newer +ABI than the firmware fails the other way, with ``Exported symbol +"__nxflat_abi_vN" not found`` and ``ENOENT``. + +The marker resolves like any other import, so the exported symbol table +passed to ``exec()`` has to contain it. A table generated from the modules' +thunk files, the way ``apps/tools/mksymtab.sh`` generates one, picks it up +automatically; a hand-written table has to list it. + Where the ARM PIC flags come from --------------------------------- @@ -346,8 +379,8 @@ to say something when it differs from the default:: ``ARCHPICFLAGS`` uses ``?=``, and the two derived variables use deferred ``=``, so a board that includes this file may still override ``ARCHPICFLAGS`` afterwards or append to it, and ``CFLAGS`` is whatever the -board finally set it to. A few boards do differ: one adds ``-ffixed-r9`` -and one conditionally adds ``-mno-pic-data-is-text-relative``. +board finally set it to. One board does differ: lm3s6965-ek conditionally +appends ``-mno-pic-data-is-text-relative``. Reserving r9 in the base firmware --------------------------------- @@ -387,7 +420,7 @@ without PIC: .. code-block:: asm ldr r1, .L0 /* Fetch the offset to 'x' */ - ldr r0, [r10, r1] /* Load the value of 'x' with PIC offset */ + ldr r0, [r9, r1] /* Load the value of 'x' with PIC offset */ /* ... */ .L0: .word x /* Offset to 'x' */ @@ -397,7 +430,7 @@ generate code like this: .. code-block:: asm ldr r1, .L0 /* Fetch the offset to the GOT entry */ - ldr r1, [r10, r1] /* Fetch the (relocated) address of 'x' from the GOT */ + ldr r1, [r9, r1] /* Fetch the (relocated) address of 'x' from the GOT */ ldr r0, [r1, #0] /* Fetch the value of 'x' */ /* ... */ .L1 .word x(GOT) /* Offset to entry in the GOT */ diff --git a/Documentation/platforms/arm/rp23xx/boards/pimoroni-pico-2-plus/index.rst b/Documentation/platforms/arm/rp23xx/boards/pimoroni-pico-2-plus/index.rst index 4dc1f70f3bc..8269cc7788c 100644 --- a/Documentation/platforms/arm/rp23xx/boards/pimoroni-pico-2-plus/index.rst +++ b/Documentation/platforms/arm/rp23xx/boards/pimoroni-pico-2-plus/index.rst @@ -181,5 +181,5 @@ xipfs-nxflat ------------ Same as ``xipfs``, plus the NXFLAT execute-in-place demo. Building this -configuration requires the NXFLAT tools (``mknxflat`` and ``ldnxflat``), -which are not part of a standard toolchain installation. +configuration requires ``ldnxflat``, which is not part of a standard +toolchain installation; see :doc:`/components/nxflat`.
