mirror of
https://github.com/apache/nuttx.git
synced 2026-09-15 07:01:05 +00:00
A function pointer under FDPIC is not a code address. Because each PT_LOAD segment is placed independently, a pointer has to carry the data base its callee will need, so it is a two-word descriptor: the entry point, and the base to install in the PIC register before branching. R_ARM_FUNCDESC_VALUE says "the thing you are patching is such a descriptor", and R_ARM_FUNCDESC says "manufacture one and give me its address". Both need state a relocation cannot carry. A descriptor's second word is the *object's* data base, from DT_PLTGOT, and R_ARM_FUNCDESC carves descriptors from a pool whose cursor has to survive from one relocation to the next. up_relocate() is handed only a relocation, a resolved symbol and an address to patch. arch_data is the existing channel for exactly this -- RISC-V already uses it to remember a HI20 relocation while its LO12 partner is processed -- but nothing has ever put loader state into it: it is declared zeroed and written only by up_relocate() itself. So ARCH_ELFDATA_INIT and ARCH_ELFDATA_FINI are added, seeding the block from the loadinfo before the relocation loop and reading the cursor back after. Both default to nothing, so an architecture that does not define them is unaffected, and RISC-V's use of arch_data is untouched. libelf_relocatedyn() walks both dynamic tables under one arch_data, so the cursor spans the whole object. The addend handling is the part that is easy to get wrong. REL format keeps the addend in place, in the word about to become the entry point, and a pointer to a static function is referenced through its *section* symbol -- the value is the section base and the offset, including the Thumb bit, is entirely in the addend. Dropping it yields an even address and the core faults trying to execute it as ARM code. The GOT written into a descriptor is the loading object's own, even for an imported function, which is what makes a callback work: when the base firmware's qsort() calls back into a module's comparison function, the module needs its own data base in the PIC register. libelf_relocatedyn()'s imported-symbol path needed a change to suit. It stores the resolved address directly and never calls up_relocate(), which cannot produce a two-word descriptor, so under FDPIC the resolved value now goes through up_relocate() and the relocation type decides what to write. Implemented for armv7-m and armv8-m, the profiles FDPIC targets; the other ARM variants gain the arch_data block but no new relocations. Built and booted mps3-an547:picostest and lm3s6965-ek:qemu-nxflat, the ELF PIC and NXFLAT users of this code, both unchanged. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com> |
||
|---|---|---|
| .. | ||
| aio | ||
| assert | ||
| audio | ||
| builtin | ||
| ctype | ||
| dirent | ||
| dlfcn | ||
| elf | ||
| errno | ||
| eventfd | ||
| fdt | ||
| fixedmath | ||
| gdbstub | ||
| gnssutils | ||
| grp | ||
| hex2bin | ||
| inttypes | ||
| libgen | ||
| locale | ||
| lzf | ||
| machine | ||
| misc | ||
| net | ||
| netdb | ||
| obstack | ||
| pthread | ||
| pwd | ||
| queue | ||
| regex | ||
| sched | ||
| search | ||
| semaphore | ||
| signal | ||
| spawn | ||
| stdio | ||
| stdlib | ||
| stream | ||
| string | ||
| symtab | ||
| syslog | ||
| termios | ||
| time | ||
| tls | ||
| uio | ||
| unistd | ||
| userfs | ||
| uuid | ||
| wchar | ||
| wctype | ||
| wqueue | ||
| zoneinfo | ||
| .gitignore | ||
| CMakeLists.txt | ||
| Kconfig | ||
| libc.csv | ||
| libc.h | ||
| limits_check.c | ||
| Makefile | ||