Skip to content

examples/fdpicxip, testing/fs/xipfs: A DT_NEEDED library is one instance - #3693

Merged
xiaoxiang781216 merged 2 commits into
apache:masterfrom
casaroli:fdpic-apps
Aug 7, 2026
Merged

examples/fdpicxip, testing/fs/xipfs: A DT_NEEDED library is one instance#3693
xiaoxiang781216 merged 2 commits into
apache:masterfrom
casaroli:fdpic-apps

Conversation

@casaroli

@casaroli casaroli commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Summary

examples/fdpicxip and testing/fs/xipfs assert that each running instance of a module gets its own copy of a library named in DT_NEEDED: two instances adding their own seed each saw a total of seed * 3.

That was true of the loader that walked DT_NEEDED itself. The loader now hands the work to dlopen(), which returns the object already in the module registry rather than loading a second copy, so there is one library and one set of its globals, shared by every module that names it. The module's own data stays private per instance, because exec() loads the module afresh each time.

What an instance can still assert on its own is that every add it made landed in the library, so that is what it checks. The test additionally checks the consequences: the library is pinned once rather than once per instance, and its destructor runs once, at the last close, holding what both instances built up.

The embedded module blobs are regenerated from the sources beside them.

depends-on: [apache/nuttx/pull/19673]

Testing

Run in full on QEMU mps2-an500 and on a Pimoroni Pico Plus 2 (RP2350), against apache/nuttx#19673.

xipfs_test          131 passed, 0 failed
xipfs_test fdpic     34 passed, 0 failed
xipfs_test reject     7 passed, 0 failed
fdpicxip qsort | solib | cxx | jmprel

Comment thread examples/fdpicxip/modules/cxxuser.cpp
FDPICDIR = $(NUTTX_DIR)/tools/fdpic
MODULE_MK = $(FDPICDIR)/nuttx-fdpic.mk
EMBED = $(FDPICDIR)/fdpic-embed
EMBED = $(FDPICDIR)/fdpic-embed.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we integrate fdpic special process into the post link after you corporate fdpic into elf binfmt?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for building fdpic modules, we can do with stock gcc, however for linking them we need upstream binutils rebuilt with arm-uclinuxfdpiceabi-ld, as stock arm ld does not ship with it:

$ arm-none-eabi-ld -V
GNU ld (Arm GNU Toolchain 15.2.Rel1) 2.45.1
  Supported emulations:
   armelf

What do you suggest? can we include the "custom" binutils in the CI image?

@xiaoxiang781216 xiaoxiang781216 Aug 7, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can change LD in Tooldefine.def to the special version if CONFIG_FDPIC is enabled.

What do you suggest? can we include the "custom" binutils in the CI image?

we can add the prebuilt tool to Dockfile directly:
https://github.com/apache/nuttx/blob/master/tools/ci/docker/linux/Dockerfile
if the tool doesn't have the official release binary, we can build from scratch like bloaty:
https://github.com/apache/nuttx/blob/master/tools/ci/docker/linux/Dockerfile

The two helper scripts this Makefile names gained a file extension when
tools/fdpic came into the nuttx tree: checkpatch rejects an executable file
that is not .sh, .py or .bat.

Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
…nce.

Both the demo and the test asserted that each running instance of a module
gets its own copy of a library named in DT_NEEDED: two instances adding
their own seed each saw a total of seed*3.

That was true of the loader that walked DT_NEEDED itself.  The loader now
hands the work to dlopen(), which returns the object already in the module
registry rather than loading a second copy of it, so there is one library
and one set of its globals, shared by every module that names it.  The
module's own data stays private per instance, because exec() loads the
module afresh each time.

What an instance can still assert on its own is that every add it made
landed in the library, so that is what it checks; the totals interleave and
the final one counts both.  The test additionally checks the consequences:
the library is pinned once rather than once per instance, and its
destructor runs once, at the last close, holding what both instances built
up.

USER_FAIL_PRIVATE becomes USER_FAIL_SHARED rather than gaining a
companion.  The bit is a private protocol between cxxuser.cpp, which sets
it, and testing/fs/xipfs, which reads it; nothing else names it, and the
property it used to report no longer exists.

Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
@xiaoxiang781216
xiaoxiang781216 merged commit 6e61ce7 into apache:master Aug 7, 2026
12 of 41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants