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]
