nuttx/libs/libc
Marco Casaroli dcd93b0f67
Some checks are pending
Build Documentation / build-html (push) Waiting to run
MemBrowse Memory Report / changes-filter (push) Waiting to run
MemBrowse Memory Report / load-targets (push) Waiting to run
MemBrowse Memory Report / identical (push) Blocked by required conditions
MemBrowse Memory Report / analyze (push) Blocked by required conditions
libs/libc/elf: Load the libraries a module names in DT_NEEDED.
A module that names a shared library in DT_NEEDED now gets it loaded and
its imports bound against it, rather than being refused.

libelf_insert() does the loading, which is what dlopen() calls anyway: the
library lands in the module registry like anything else, its exports come
back through libelf_getsymbol() -- the same call dlsym() uses -- and a
library named by two modules is loaded once.  A bare name is looked for
along LD_LIBRARY_PATH, where dlopen() looks for it.  Undefined symbols
resolve against the globally registered symbols first, then the modules
this one depends on, then the table exec() supplied.  Nothing here calls
into dlfcn, because this loader is also the kernel's module loader, which
has none.

Each library becomes one of the module's dependencies[], and the dependency
holds it in place of the reference libelf_insert() took.  So a library
loaded only for DT_NEEDED is kept by the modules that depend on it, and
libelf_undepend() unloads it with the last of them; one that dlopen() or
insmod also opened stays until that reference goes too.
CONFIG_LIBC_ELF_MAXDEPEND bounds how many libraries a module may name,
which is what it already meant.

Six things had to be fixed to make it work, none of which a build shows.

reldata was a file-scope global.  Loading a library from inside
libelf_relocatedyn() makes that function reentrant, so the nested load
overwrote the outer one's relocation offsets and the module resumed binding
with the library's DT_REL.  It is now per call.

A cross-object call needs the callee's data base, not the caller's.  A
symbol resolved from an FDPIC library comes back as a descriptor, and
R_ARM_FUNCDESC_VALUE was treating it as a code address and pairing it with
the importing module's GOT.  It now copies both words, so the library runs
with its own.

An object with no imports has no PLT and so no DT_PLTGOT, but it still has
a GOT and still has to be entered with it.  Without the fallback its
descriptors carried a data base of zero and the library read its globals
through a null pointer.

R_ARM_FUNCDESC, a pointer to a descriptor, wrapped a library's descriptor
in a second one.  It now stores the library's descriptor as it is.

The flag that says a resolved value is a descriptor was set only for an
import and never cleared, so the next relocation against a symbol of the
module itself took that symbol for a descriptor too.  It is cleared there.

libelf_symname() was static, and reading a DT_NEEDED name needs it.

A module with DT_NEEDED is refused where CONFIG_LIBC_ELF_MAXDEPEND is zero,
since that is where the dependency logic is compiled out.

A DT_NEEDED library is one shared instance, its data included, because the
loader returns the object already in the registry.  A module started with
exec() is different: that path loads the module afresh each time, so two
running instances have separate data while sharing one copy of the text.

Built for mps3-an547:picostest with CONFIG_FDPIC both ways.  Run on
mps2-an500:xipfs under QEMU: fdpicxip solib loads libcounter.so by name out
of DT_NEEDED, two instances share one pinned copy of its text, and the
library is unloaded, and its pin given back, when the second one exits.  A
library also opened with dlopen() stays loaded after its DT_NEEDED user
exits, and dlclose() unloads it.

With CONFIG_ARCH_ADDRENV the program runs in its own address space, which
a library libelf_insert() loads cannot reach, so DT_NEEDED is refused
there as before.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-10-06 17:48:49 -03:00
..
aio libc/aio: loop in aio_suspend() until a listed request completes 2026-09-14 17:12:49 -03:00
assert lib_stackchk.c: a duplicate implementation error reported during compilation 2026-02-02 13:22:07 +08:00
audio include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
builtin libc/builtin: support per-application priority/stacksize under KERNEL build. 2026-07-13 15:23:39 -03:00
ctype style: fix spelling in code comments and strings 2025-05-23 10:48:41 +08:00
dirent libs/libc/dirent: Add a blank line after a declaration. 2026-09-25 10:46:48 -03:00
dlfcn libc/dlfcn: Count opens so a library can be shared. 2026-08-04 11:12:49 -03:00
elf libs/libc/elf: Load the libraries a module names in DT_NEEDED. 2026-10-06 17:48:49 -03:00
errno libs/libc: migrate to SPDX identifier 2024-10-01 12:25:52 +08:00
eventfd libs/libc: migrate to SPDX identifier 2024-10-01 12:25:52 +08:00
fdt cmake: Use NUTTX(_DIR/_BIN_DIR) instead CMAKE(_SRC_DIR/_BIN_DIR) 2026-08-09 11:13:08 -03:00
fixedmath !compiler: drop CONFIG_HAVE_LONG_LONG and require long long support 2026-05-19 16:21:28 +08:00
gdbstub arch/arm64: fix backtrace register access and gdbstub config guard 2026-01-16 08:55:47 -03:00
gnssutils cmake: Use NUTTX(_DIR/_BIN_DIR) instead CMAKE(_SRC_DIR/_BIN_DIR) 2026-08-09 11:13:08 -03:00
grp libs/libc/grp: fix getgrbuf_r() pointer-alignment padding 2026-08-14 10:20:52 +08:00
hex2bin include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
inttypes !compiler: drop CONFIG_HAVE_LONG_LONG and require long long support 2026-05-19 16:21:28 +08:00
libgen libs/libc: migrate to SPDX identifier 2024-10-01 12:25:52 +08:00
locale style/FAR: remove FAR qualifier 2025-11-10 10:56:29 +01:00
lzf !compiler: drop CONFIG_HAVE_LONG_LONG and require long long support 2026-05-19 16:21:28 +08:00
machine libs/libc/elf: Load the libraries a module names in DT_NEEDED. 2026-10-06 17:48:49 -03:00
misc libs/libc: Define the NXFLAT ABI marker in libc. 2026-09-28 16:45:48 -03:00
net include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
netdb libs/libc/netdb: Size an answer header by its header, not by its union. 2026-08-08 15:02:15 -03:00
obstack include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
pthread libc, sched: Resolve FDPIC descriptors at module callback entry points. 2026-09-25 10:46:48 -03:00
pwd sched: add supplementary group IDs (setgroups/getgroups/initgroups) 2026-08-12 16:06:03 -03:00
queue libs/libc: migrate to SPDX identifier 2024-10-01 12:25:52 +08:00
regex libs/libc/regex: remove logically dead code in regcomp.c 2026-01-24 19:28:56 +08:00
sched include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
search libc/search: add foreach api for hcreate_data 2025-12-25 09:39:03 +08:00
semaphore sched/semaphore: Correct the return value comment of nxsem_init/nxmutex_init 2026-09-25 10:37:43 +02:00
signal signal: Inline nxsig_addset(), nxsig_delset() and nxsig_ismember(). 2026-10-06 17:45:52 -03:00
spawn spawn: allow zero stacksize/priority to use binary loader defaults 2026-07-15 12:24:44 -03:00
stdio libc/stdio: allocate a buffer in getdelim() when *lineptr is NULL 2026-09-23 12:52:09 +08:00
stdlib libc, sched: Resolve FDPIC descriptors at module callback entry points. 2026-09-25 10:46:48 -03:00
stream libc/stream: Check lowout bounds before access 2026-07-06 09:02:22 +02:00
string libs/libc/string: Copy and compare by words when pointers agree on alignment. 2026-08-24 12:02:02 +08:00
symtab libs/libc/symtab: fix bogus symbol size under SYMTAB_ORDEREDBYNAME 2026-08-05 21:51:25 +08:00
syslog drivers/syslog: Add RFC 5424 protocol support 2025-06-13 20:26:57 +08:00
termios libc/termios: Fix the ttyname_r buffer overflow with long tty paths. 2026-10-05 18:42:52 +08:00
time libc/time: Fix POSIX timezone string parsing. 2026-07-25 19:54:18 +08:00
tls libc/tls: update preprocessor condition comment to match implementation 2026-01-31 02:49:10 +08:00
uio move readv/writev to the kernel 2024-10-30 17:07:54 +08:00
unistd fs/aio: add configurable AIO_LISTIO_MAX limit 2026-09-14 17:12:49 -03:00
userfs include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
uuid libc: Refine the arc4random_buf implementation 2024-10-26 18:04:21 -03:00
wchar style: fix spelling in code comments and strings 2025-05-23 10:48:41 +08:00
wctype libs/libc: migrate to SPDX identifier 2024-10-01 12:25:52 +08:00
wqueue libc/wqueue: use the uninterruptible wait helper 2026-09-04 23:02:48 +08:00
zoneinfo tools: fix stale archive members surviving a Kconfig-driven CSRCS change 2026-07-28 21:26:03 -03:00
.gitignore libc/elf: rename modlib to libelf 2025-04-11 09:43:22 +08:00
CMakeLists.txt libs/libc: migrate to SPDX identifier 2024-10-01 12:25:52 +08:00
Kconfig libc/elf: rename modlib to libelf 2025-04-11 09:43:22 +08:00
libc.csv sched/pthread: Implement pthread_sigqueue 2026-09-21 14:53:26 +08:00
libc.h libs/libc/string: Copy and compare by words when pointers agree on alignment. 2026-08-24 12:02:02 +08:00
limits_check.c libs/libc: add limits checks 2026-07-02 09:02:21 -03:00
Makefile tools: fix stale archive members surviving a Kconfig-driven CSRCS change 2026-07-28 21:26:03 -03:00