casaroli opened a new pull request, #20368:
URL: https://github.com/apache/nuttx/pull/20368

   depends-on: [apache/nuttx/pull/20131]
   
   ## Summary
   
   `[8/10]` #20131 loads an FDPIC module.  A module that names a shared library 
in `DT_NEEDED` is still refused, and this loads it and binds the module's 
imports against it.
   
   `dlopen()` does the loading.  It is already the loader for a shared library, 
so the work goes there rather than into a dependency walker of the loader's 
own: the library lands in the module registry like anything else, its exports 
come back through `libelf_getsymbol()`, which is the call `dlsym()` uses, and a 
library named by two modules is opened once and reference counted.  Undefined 
symbols are resolved against the globally registered symbols first, then the 
opened libraries, then the table `exec()` supplied.  The handles are closed 
when the module is removed.
   
   Four things had to be fixed to make it work, none of which a build shows.
   
   `reldata` was a file-scope global.  Opening 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 per call now.
   
   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 copies both words now, 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.
   
   `libelf_symname()` was static, and reading a `DT_NEEDED` name needs it.
   
   `CONFIG_FDPIC` now depends on the flat build.  A module's read-only segment 
is held by a filesystem pin that is given back when the module is unloaded, on 
a task other than the one that loaded it, so it is held through a reference to 
the file rather than a descriptor -- and the file interface is not reachable 
from the loader in the protected and kernel builds.  Selecting it there would 
leak the pin and leave the filesystem unable to compact.
   
   ## Impact
   
   Nothing happens without `CONFIG_LIBC_DLFCN`: a module with `DT_NEEDED` is 
refused there, as before, since there is no way to load what it asks for.
   
   A `DT_NEEDED` library is one shared instance, its data included, because 
`dlopen()` 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.
   
   `CONFIG_LIBC_ELF_MAXNEEDED` bounds how many libraries one module may name, 
and defaults to four.
   
   ## Testing
   
   `mps3-an547:picostest` builds three ways on top of `[8/10]`: with 
`CONFIG_FDPIC` off, with it on, and with it on plus `CONFIG_LIBC_DLFCN`, which 
is the path this patch adds.  With `CONFIG_FDPIC` on, the applications the 
configuration carries are FDPIC objects (`OS/ABI: ARM FDPIC`).
   
   `tools/checkpatch.sh -c -u -m -g` passes.
   
   ## Review
   
   Draft until `[8/10]` merges, because it changes the same `elf_bind.c` and 
`elf_remove.c`.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to