dlopen() of a library that is already loaded fails. libelf_insert()
rejects a name that is already in the module registry with EEXIST, and
dlinsert() passes that straight out, so the second caller gets NULL.
POSIX says dlopen() shall return a handle to the object, and there is no
way today for two modules to hold the same library at once -- which is
what a shared library is for.
So dlopen() now takes another reference on a library that is already
there, and dlclose() only tears it down when the last handle goes. The
count lives in the dlfcn layer rather than in libelf_insert() so that
insmod keeps its own behaviour: a second insmod of the same name still
fails with EEXIST, which is right for a kernel module.
The module name is what makes any of this possible, and a PROTECTED build
did not have one. Names were defined for CONFIG_BUILD_FLAT or the kernel
side of a split build, on the reasoning that only the kernel needed them,
which predates dlopen() being usable from user space. Without a name the
user-space copy of libelf cannot recognise a second open of a library,
cannot count opens, and cannot make dlclose() mean anything -- two
dlopen()s there produce two independent copies of the library and lose
track of the first. Names are therefore defined wherever CONFIG_LIBC_DLFCN
is, which costs NAME_MAX per loaded module in that configuration.
The path no longer has to be copied either. The module name is the
basename of the file and libelf_insert() takes it as a const string, so
dlinsert() finds it with strrchr() instead of handing a writable
duplicate of the whole path to basename().
BUILD_KERNEL is deliberately untouched. dlopen() returns NULL there
unconditionally: dlinsert() is a stub, because sharing a library between
processes with separate address spaces needs the text in a shared region
and the data per process at a matching virtual address, which is a
different problem from this one.
Built for mps3-an547:picostest with and without CONFIG_LIBC_DLFCN, and
for stm32f4discovery:kostest, a PROTECTED configuration, with it enabled.
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>