nuttx/binfmt
Marco Casaroli d5b4edd761 binfmt/fdpic: Run constructors, and bind the PLT relocation table.
Two gaps that both fail quietly.

DT_INIT_ARRAY and DT_FINI_ARRAY were ignored entirely.  A C++ module with
any global object therefore loaded, resolved every symbol and ran, with all
of its globals left as .bss reading back zero -- no fault, no log, just
wrong answers.  Both arrays are now walked per object and in dependency
order: an object joins the load's list before the DT_NEEDED walk appends its
own dependencies, so walking that list backwards constructs a library before
the module that needs it, and destruction mirrors it.

Constructors run in whichever task called the loader, before the module's
own task exists, so the FDPIC register does not already hold the object's
data base the way it does once the module is running.  fdpic_callfn()
installs it around each call.  That is safe only because the firmware
reserves the register; being preempted mid-constructor is harmless, since
the register is part of the saved context.

DT_JMPREL was not parsed at all.  Which table an imported function's
descriptor lands in is a linker decision -- -z now puts it in DT_REL, and
without it the same entry goes to DT_JMPREL -- so a module linked the second
way loaded cleanly and then branched to an unrelocated address on its first
call into the firmware.  The symptom is an INVSTATE UsageFault escalated to
a HardFault: no console, no crash dump.  There is no lazy resolver here, so
an unwalked table is not deferred work; both are now bound eagerly, and
nothing is lost by that because a module carries a handful of relocations.

The two tables are not walked identically, which is the part worth
remembering.  In DT_REL the word being overwritten is the addend, and
dropping it breaks a static function reached through its section symbol.  In
DT_JMPREL that same word is the lazy-binding bootstrap -- the address of the
entry's own PLT resolution stub, with a GOT half of -1 -- and adding it to
the resolved symbol value produces an arbitrary address that faults exactly
like the bug this change fixes.  An eager binder overwrites the descriptor
outright.

The descriptor pool is sized from relsize + pltrelsz rather than relsize
alone, so an R_ARM_FUNCDESC in the PLT table cannot run off the end of the
allocation.  GNU ld does not appear to emit that combination -- an
address-taken function is not a call and so never becomes a PLT relocation
-- but the failure it would cause is heap corruption, and the guard is two
additions.

An object declaring RELA PLT relocations is refused rather than misread:
nothing here reads RELA, whose entries are twelve bytes rather than eight.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-08-01 12:23:27 +02:00
..
libnxflat include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
binfmt.h binfmt/fdpic: Add an FDPIC ELF module loader. 2026-08-01 12:23:27 +02:00
binfmt_checkexec.c fs/binfmt: Enforce POSIX execute permissions prior to binary load 2026-06-13 21:07:01 +08:00
binfmt_copyactions.c include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
binfmt_copyargv.c include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
binfmt_dumpmodule.c include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
binfmt_exec.c fs/binfmt: Enforce POSIX execute permissions prior to binary load 2026-06-13 21:07:01 +08:00
binfmt_execmodule.c include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
binfmt_execsymtab.c sched: binfmt remove csection 2026-01-11 20:44:35 +08:00
binfmt_exit.c include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
binfmt_globals.c binfmt: migrate to SPDX identifier 2024-09-10 11:34:18 +08:00
binfmt_initialize.c binfmt/fdpic: Add an FDPIC ELF module loader. 2026-08-01 12:23:27 +02:00
binfmt_loadmodule.c fs/binfmt: Enforce POSIX execute permissions prior to binary load 2026-06-13 21:07:01 +08:00
binfmt_register.c include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
binfmt_unloadmodule.c include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
binfmt_unregister.c include/debug.h: Move to include/nuttx/debug.h 2026-04-07 07:50:06 -03:00
builtin.c fs/binfmt: Enforce POSIX execute permissions prior to binary load 2026-06-13 21:07:01 +08:00
CMakeLists.txt binfmt/fdpic: Add an FDPIC ELF module loader. 2026-08-01 12:23:27 +02:00
elf.c elf:use elf symbol to parse attribute 2026-07-15 12:24:44 -03:00
fdpic.c binfmt/fdpic: Run constructors, and bind the PLT relocation table. 2026-08-01 12:23:27 +02:00
Kconfig binfmt/fdpic: Add an FDPIC ELF module loader. 2026-08-01 12:23:27 +02:00
Makefile binfmt/fdpic: Add an FDPIC ELF module loader. 2026-08-01 12:23:27 +02:00
nxflat.c fs/binfmt: Enforce POSIX execute permissions prior to binary load 2026-06-13 21:07:01 +08:00