Conversation
|
🔗 Cross-repo PR dependenciesThe read-only Build run reported the following dependent PR(s) and fetched head SHA(s):
CI run: https://github.com/apache/nuttx/actions/runs/34775786256 |
59f570a to
cefa2eb
Compare
🔗 Cross-repo PR dependenciesThe read-only Build run reported the following dependent PR(s) and fetched head SHA(s): CI run: https://github.com/apache/nuttx/actions/runs/34957863761 |
cefa2eb to
3a2ce9e
Compare
🔗 Cross-repo PR dependenciesThe read-only Build run reported the following dependent PR(s) and fetched head SHA(s): CI run: https://github.com/apache/nuttx/actions/runs/35060360729 |
3a2ce9e to
27a868a
Compare
27a868a to
03827a0
Compare
|
|
||
| if (modp->xipbase == 0) | ||
| { | ||
| #if defined(CONFIG_ARCH_USE_TEXT_HEAP) |
There was a problem hiding this comment.
#ifdef CONFIG_ARCH_USE_TEXT_HEAP
| * unloading thread does not carry. | ||
| */ | ||
|
|
||
| gotbase = modp->fdpic ? modp->gotbase : 0; |
There was a problem hiding this comment.
why need? gotbase should be zero if fdpic equals false.
| for (i = 0; i < modp->nfini; i++) | ||
| { | ||
| array[i](); | ||
| fdpic_call(array[i], gotbase); |
There was a problem hiding this comment.
gotbase->modp->gotbase
| * none of its own. | ||
| */ | ||
|
|
||
| gotbase = loadinfo.fdpic ? loadinfo.gotbase : 0; |
| case DT_PLTRELSZ: | ||
| reldata.relsz[I_PLT] = dyn[i].d_un.d_val; | ||
| break; | ||
| case DT_NEEDED: |
There was a problem hiding this comment.
let's move to DT_NEEDED patch
| * | ||
| ****************************************************************************/ | ||
|
|
||
| static inline void fdpic_call(CODE void (*fn)(void), uintptr_t got) |
There was a problem hiding this comment.
should we pass arg like fdpic_invoke
| uint16_t nsect; /* Number of entries in sectalloc array */ | ||
| #endif | ||
| int dynamic; /* Module is a dynamic shared object */ | ||
| bool fdpic; /* Module is an FDPIC object: its two |
exec() of an FDPIC module now works. The loader already places such an object and binds it; what was missing is everything binfmt has to carry across from the load to the running task. The task needs the module's data base in its PIC base register. binfmt builds a D-Space for any object with a GOT, taking the base from the .got section address; an FDPIC object names it in DT_PLTGOT instead, which the loader has already translated, so the two are the same idea reached by different routes and both are what up_initial_state() installs. Constructors are not binfmt's business. A module carries its own crt0, which walks .init_array on the task that runs the module and then calls main, so they run in the module's own context and with its own data base. For a module that arrives through dlopen(), libelf_insert() walks the array instead, and it enters each entry through fdpic_invoke() because a descriptor resolved on the calling task carries the wrong base. The read-only segment of a module that executes in place is held by a filesystem pin. The load takes it, and the module owns it from the point where nothing can fail any more; it is given back when the task that runs the module exits. The pin is held through a reference to the file rather than a descriptor, because the descriptor belongs to the task that called the loader and the release happens on another one. libelf_remove() and libelf_uninit() give back what an FDPIC module holds: the pin, and the writable segment, while the read-only one is media rather than an allocation and must not be freed. Built for mps3-an547:picostest with CONFIG_FDPIC both ways. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
03827a0 to
39614ff
Compare
Summary
[5/10]#19942,[6/10]#20089 and[7/10]#20130 are merged: an FDPIC object is placed, bound and relocated, and the firmware can call back into it. This makesexec()of one work.The task needs the module's data base in its PIC base register. binfmt builds a D-Space for any object with a GOT, taking the base from the
.gotaddress; an FDPIC object names it inDT_PLTGOTinstead, which the loader has already translated. The two are the same idea reached by different routes, and both are whatup_initial_state()installs.Constructors are not binfmt's business. A module carries its own crt0, which walks
.init_arrayon the task that runs the module and then callsmain, so they run in the module's own context with its own data base. For a module arriving throughdlopen(),libelf_insert()walks the array instead, entering each entry throughfdpic_invoke(), because a descriptor resolved on the calling task carries the wrong base.The read-only segment of a module that executes in place is held by a filesystem pin. The load takes it, and the module owns it from the point where nothing can fail any more; it is given back when the task exits. The pin is held through a reference to the file rather than a descriptor, because the descriptor belongs to the task that called the loader while the release happens on another.
libelf_remove()andlibelf_uninit()give back what an FDPIC module holds: the pin, and the writable segment. The read-only one is media rather than an allocation and must not be freed.Impact
Behind
CONFIG_FDPIC, which defaults off. With it off, binfmt is what it was.Testing
mps3-an547:picostestbuilds on master withCONFIG_FDPICoff and on. With it on, the apps the configuration carries come out as FDPIC objects (OS/ABI: ARM FDPIC), which is what this patch loads.The constructor and destructor loops enter the module through
fdpic_invoke(), which[7/10]defines and which is now in master.tools/checkpatch.sh -c -u -m -gpasses.Review
Everything below this in the series is merged, so it stands on master by itself.