Commit graph

13 commits

Author SHA1 Message Date
Marco Casaroli
50a735bf86 libs/libc/machine/arm: Relocate FDPIC function descriptors.
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>
2026-09-13 16:03:32 -03:00
Marco Casaroli
1aa32bbc07 libs/libc/elf: Place an FDPIC object's segments independently.
An ET_DYN object is loaded into one allocation with its data behind its
text, because its data references sit at a fixed distance from the code
that makes them.  An FDPIC object does not work that way: it reaches its
data through a base register, so the two segments can be placed wherever
suits, and the point of the format is that the read-only one is left on
the media and executed there while only the writable one is copied.  One
copy of the text then serves every instance.

So libelf_load() grows a second case.  The object announces itself in the
OS/ABI byte, which is noted once in libelf_loadhdrs() rather than
re-derived; e_flags cannot be used for this, as an FDPIC object's are an
unremarkable EABI version and testing them would reject every valid
module.  Text is taken from the media address plus the segment's own file
offset -- the same arithmetic the ET_REL path already does with
sh_offset -- and libelf_loadfile() does not read it.  If the filesystem
cannot show its media, the loader copies the text to RAM instead.  The
module then loses the shared text and the flash saving, but it runs.

Obtaining that address needs two mechanisms, and they are not
interchangeable.  A compacting filesystem can move a file's blocks, so it
hands out an address only with a pin that holds them still and expects
the pin back; xipfs is the one in tree.  A filesystem whose layout never
changes has nothing to hold and answers FIOC_XIPBASE with a bare address;
romfs and tmpfs are those.  libelf_xipacquire() asks for the pin first,
because a filesystem that needs one is not safe without it, and
libelf_unload() gives it back.  The loader asks for a pin only if it can
hold one, or the pin would stay for ever.

The pin is thus not specific to FDPIC.  Any module that executes in place
from a compacting filesystem takes one, and gives it back at unload.

mmap() is not used, though both filesystems implement it.  The mapping
would be recorded against whichever task called the loader, while the
release happens when the module's own task exits, which is a different
group -- so the pin would outlive the module and the extent would never
become movable again.

Unloading has to change with placement: the existing path frees only
textalloc because ET_DYN had a single allocation, which would leak an
FDPIC object's data and free media the filesystem only lent us.

Nothing here runs for a non-FDPIC object; every branch is behind the flag
and the single-allocation path is untouched.  Built and booted
mps3-an547:picostest, which is CONFIG_ELF with CONFIG_PIC, with no change
in behaviour.

Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-09-08 16:31:16 -03:00
Alin Jerpelea
344968b8c2 arch/arm: migrate to SPDX identifier
Most tools used for compliance and SBOM generation use SPDX identifiers
This change brings us a step closer to an easy SBOM generation.

Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
2024-12-06 09:25:23 +08:00
Xiang Xiao
813b652ba5 elf: Move 32/64bit generic mapping from risc-v/arch_elf.c to elfxx.h
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2023-07-10 13:09:47 -03:00
Xiang Xiao
70290b6e38 arch: Change the linker generated symbols from uint32_t to uint8_t *
and remove the duplicated declaration

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2022-09-24 21:26:56 +02:00
chao.an
7cbb8da692 binfmt/elf: add bare metal coredump support
Signed-off-by: chao.an <anchao@xiaomi.com>
2021-11-23 20:48:00 -06:00
chao.an
4c76c356ef arch/arm: add more arch elf define
Signed-off-by: chao.an <anchao@xiaomi.com>
2021-11-23 20:34:56 +09:00
Alin Jerpelea
c39339a7a8 arch: arm: include: nxstyle fixes
nxstyle fixes to pass CI

Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
2021-03-22 19:28:38 -07:00
Alin Jerpelea
4daa276903 arch: arm: include: Author Gregory Nutt: update licenses to Apache
Gregory Nutt has submitted the SGA and we can migrate the licenses
 to Apache.

Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
2021-03-22 19:28:38 -07:00
Xiang Xiao
bda6d7f065 arch/arm/include/syscall.h: Add missing inclusion of arch/armv7-r/syscall.h for CortexR. 2019-01-26 07:43:31 -06:00
Gregory Nutt
25d4ff745b More trailing whilespace removal 2014-04-13 16:22:22 -06:00
patacongo
0074eca835 Rename elf.h to elf32.h; Additional ELF loader changes
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5263 42af7a65-404d-4744-a932-0658087f49c3
2012-10-26 02:42:39 +00:00
patacongo
cce736ef83 Add an ARM ELF header file
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5262 42af7a65-404d-4744-a932-0658087f49c3
2012-10-25 23:52:50 +00:00