nuttx/libs/libc/elf/elf_load.c

1043 lines
30 KiB
C
Raw Normal View History

/****************************************************************************
* libs/libc/elf/elf_load.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/param.h>
#include <sys/types.h>
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-08-03 00:56:27 +02:00
#include <inttypes.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/debug.h>
#include <nuttx/arch.h>
libs/libc/elf: Read the dynamic tags an FDPIC object needs. libelf_relocatedyn() reads the handful of DT_* tags it needs to walk the relocation tables and ignores the rest. Three more matter now. DT_PLTGOT is where the object's data base lives. An FDPIC module runs with that in the PIC base register, and every function descriptor built for it names the same base as the one its callee should run with, so without it there is nothing to put in a descriptor's second word. The DT_*_ARRAY tags are the constructor and destructor tables. These are already found through the section headers a few lines further down, and that path is kept, but the dynamic tags are the authoritative copy and an object is not obliged to carry section headers at all. Both paths now translate through libelf_addr(), so they agree on the answer rather than depending on which ran last. The tag values themselves were missing from include/elf.h and are added. Sizing the descriptor pool has to happen here rather than later. R_ARM_FUNCDESC asks the loader to manufacture a descriptor and hand back its address, which means the space must exist by the time the relocation is applied, and by then the segment has been placed. So libelf_elfsize() reserves it behind the writable data, bounded by the relocation count -- one relocation cannot ask for more than one descriptor. That bound has slack in it, but a descriptor is two words and modules are small, which is cheaper than walking every relocation twice to get an exact count. Nothing here runs for a non-FDPIC object. Built and booted mps3-an547:picostest 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-08-03 08:49:25 +02:00
#include <nuttx/fdpic.h>
#include <nuttx/lib/elf.h>
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-08-03 00:56:27 +02:00
#include <nuttx/fs/fs.h>
#include <nuttx/fs/ioctl.h>
#include "libc.h"
#include "elf/elf.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define ELF_ALIGN_MASK ((1 << CONFIG_LIBC_ELF_ALIGN_LOG2) - 1)
#define ELF_ALIGNUP(a) (((unsigned long)(a) + ELF_ALIGN_MASK) & ~ELF_ALIGN_MASK)
#define ELF_ALIGNDOWN(a) ((unsigned long)(a) & ~ELF_ALIGN_MASK)
/* _ALIGN_UP: 'a' is assumed to be a power of two */
#define _ALIGN_UP(v, a) (((v) + ((a) - 1)) & ~((a) - 1))
#ifdef CONFIG_ARCH_USE_TEXT_HEAP
# define buffer_data_address(p) \
(FAR uint8_t *)up_textheap_data_address((FAR void *)p)
#else
# define buffer_data_address(p) ((FAR uint8_t *)p)
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
static int libelf_section_alloc(FAR struct mod_loadinfo_s *loadinfo,
FAR Elf_Shdr *shdr, uint8_t idx)
{
if (loadinfo->ehdr.e_type == ET_DYN)
{
return -EINVAL;
}
if (loadinfo->sectalloc == NULL)
{
/* Allocate memory info for all sections */
loadinfo->sectalloc = lib_zalloc(sizeof(uintptr_t) *
loadinfo->ehdr.e_shnum);
if (loadinfo->sectalloc == NULL)
{
return -ENOMEM;
}
}
libelf_sectname(loadinfo, shdr);
if ((shdr->sh_flags & SHF_WRITE) != 0)
{
# ifdef CONFIG_ARCH_USE_DATA_HEAP
loadinfo->sectalloc[idx] = (uintptr_t)
up_dataheap_memalign(
(FAR const char *)loadinfo->iobuffer,
shdr->sh_addralign,
shdr->sh_size);
# else
loadinfo->sectalloc[idx] = (uintptr_t)lib_memalign(shdr->sh_addralign,
shdr->sh_size);
# endif
if (loadinfo->datastart == 0)
{
loadinfo->datastart = loadinfo->sectalloc[idx];
}
}
else if (loadinfo->xipbase != 0)
{
loadinfo->sectalloc[idx] = loadinfo->xipbase + shdr->sh_offset;
if (loadinfo->textalloc == 0)
{
loadinfo->textalloc = loadinfo->sectalloc[idx];
}
}
else
{
# ifdef CONFIG_ARCH_USE_TEXT_HEAP
loadinfo->sectalloc[idx] = (uintptr_t)
up_textheap_memalign(
(FAR const char *)loadinfo->iobuffer,
shdr->sh_addralign,
shdr->sh_size);
# else
loadinfo->sectalloc[idx] = (uintptr_t)
lib_memalign(shdr->sh_addralign,
shdr->sh_size);
# endif
if (loadinfo->textalloc == 0)
{
loadinfo->textalloc = loadinfo->sectalloc[idx];
}
}
return OK;
}
#endif
/****************************************************************************
* Name: libelf_elfsize
*
* Description:
* Calculate total memory allocation for the ELF file.
*
****************************************************************************/
static void libelf_elfsize(FAR struct mod_loadinfo_s *loadinfo, bool alloc)
{
size_t textsize = 0;
size_t datasize = 0;
int i;
/* Accumulate the size each section into memory that is marked SHF_ALLOC
* if CONFIG_ARCH_USE_SEPARATED_SECTION is enabled, allocate
* (and zero) memory for the each section.
*/
if (loadinfo->ehdr.e_type == ET_DYN)
{
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
for (i = 0; i < loadinfo->ehdr.e_phnum; i++)
{
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
FAR Elf_Phdr *phdr = &loadinfo->phdr[i];
FAR void *textaddr = NULL;
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
if (phdr->p_type == PT_LOAD)
{
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
if (phdr->p_flags & PF_X)
{
textsize += phdr->p_memsz;
textaddr = (FAR void *)(uintptr_t)phdr->p_vaddr;
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
}
else
{
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
datasize += phdr->p_memsz;
loadinfo->datasec = phdr->p_vaddr;
loadinfo->segpad = phdr->p_vaddr -
((uintptr_t)textaddr + textsize);
}
}
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
}
}
else
{
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
/* SHF_ALLOC indicates that the section requires memory during
* execution.
*/
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
if ((shdr->sh_flags & SHF_ALLOC) != 0)
{
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
/* SHF_WRITE indicates that the section address space is write-
* able
*/
if ((shdr->sh_flags & SHF_WRITE) != 0
#ifdef CONFIG_ARCH_HAVE_TEXT_HEAP_WORD_ALIGNED_READ
|| (shdr->sh_flags & SHF_EXECINSTR) == 0
#endif
)
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
{
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
if (alloc && libelf_section_alloc(loadinfo, shdr, i) >= 0)
{
continue;
}
#endif
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
datasize = _ALIGN_UP(datasize, shdr->sh_addralign);
datasize += ELF_ALIGNUP(shdr->sh_size);
if (loadinfo->dataalign < shdr->sh_addralign)
{
loadinfo->dataalign = shdr->sh_addralign;
}
}
else
{
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
if (alloc && libelf_section_alloc(loadinfo, shdr, i) >= 0)
{
continue;
}
#endif
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
textsize = _ALIGN_UP(textsize, shdr->sh_addralign);
textsize += ELF_ALIGNUP(shdr->sh_size);
if (loadinfo->textalign < shdr->sh_addralign)
{
loadinfo->textalign = shdr->sh_addralign;
}
}
}
}
}
libs/libc/elf: Read the dynamic tags an FDPIC object needs. libelf_relocatedyn() reads the handful of DT_* tags it needs to walk the relocation tables and ignores the rest. Three more matter now. DT_PLTGOT is where the object's data base lives. An FDPIC module runs with that in the PIC base register, and every function descriptor built for it names the same base as the one its callee should run with, so without it there is nothing to put in a descriptor's second word. The DT_*_ARRAY tags are the constructor and destructor tables. These are already found through the section headers a few lines further down, and that path is kept, but the dynamic tags are the authoritative copy and an object is not obliged to carry section headers at all. Both paths now translate through libelf_addr(), so they agree on the answer rather than depending on which ran last. The tag values themselves were missing from include/elf.h and are added. Sizing the descriptor pool has to happen here rather than later. R_ARM_FUNCDESC asks the loader to manufacture a descriptor and hand back its address, which means the space must exist by the time the relocation is applied, and by then the segment has been placed. So libelf_elfsize() reserves it behind the writable data, bounded by the relocation count -- one relocation cannot ask for more than one descriptor. That bound has slack in it, but a descriptor is two words and modules are small, which is cheaper than walking every relocation twice to get an exact count. Nothing here runs for a non-FDPIC object. Built and booted mps3-an547:picostest 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-08-03 08:49:25 +02:00
/* Reserve the descriptor pool. R_ARM_FUNCDESC asks the loader to
libs/libc/elf: Publish FDPIC functions as descriptors for dlsym. A module that dlopen()s a library gets back function addresses from dlsym() and calls them. Under FDPIC a bare code address is not enough: the callee needs its own data base as well, so what dlsym() returns has to be a function descriptor. The exported symbol table carries no type information -- symtab_s is a name and a value, and its own comment says typing would have to be added to support anything but function pointers -- so by the time dlsym() is asked there is no way to tell a function from an object. libelf_insertsymtab() is the last point that can: st_info is still in hand there. So an FDPIC object's exported functions are published as the address of a descriptor carved from the module's pool, and dlopen(), dlsym() and the module registry need no knowledge of FDPIC at all. The pool is sized for the dynamic symbol table as well as the relocations, since both can draw from it. That leaves the symbol values themselves, which were wrong for any ET_DYN object. libelf_loadsymtab() adds the symbol's section address to its value, which is right for ET_REL, where the section address is where the section was actually placed and the value is relative to it. In a shared object both are already full link-time addresses, so adding them counts the section twice. It needs translating onto wherever the object was placed instead. Library data is shared between everything that dlopen()s it, because the registry holds one instance per name. Giving each user its own copy would mean teaching the registry about instances, which is a much larger change to shared code; an executable loaded through exec() already gets its own data, since that path loads a fresh copy each time. Built and run on lm3s6965-ek with the examples/elf ROMFS; the FDPIC module continues to load, relocate and call through its own descriptors. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-08-03 11:34:35 +02:00
* manufacture a descriptor after the segment is placed, and a library
* publishes one per exported function for dlsym(). The relocation and
* dynamic symbol counts bound how many.
libs/libc/elf: Read the dynamic tags an FDPIC object needs. libelf_relocatedyn() reads the handful of DT_* tags it needs to walk the relocation tables and ignores the rest. Three more matter now. DT_PLTGOT is where the object's data base lives. An FDPIC module runs with that in the PIC base register, and every function descriptor built for it names the same base as the one its callee should run with, so without it there is nothing to put in a descriptor's second word. The DT_*_ARRAY tags are the constructor and destructor tables. These are already found through the section headers a few lines further down, and that path is kept, but the dynamic tags are the authoritative copy and an object is not obliged to carry section headers at all. Both paths now translate through libelf_addr(), so they agree on the answer rather than depending on which ran last. The tag values themselves were missing from include/elf.h and are added. Sizing the descriptor pool has to happen here rather than later. R_ARM_FUNCDESC asks the loader to manufacture a descriptor and hand back its address, which means the space must exist by the time the relocation is applied, and by then the segment has been placed. So libelf_elfsize() reserves it behind the writable data, bounded by the relocation count -- one relocation cannot ask for more than one descriptor. That bound has slack in it, but a descriptor is two words and modules are small, which is cheaper than walking every relocation twice to get an exact count. Nothing here runs for a non-FDPIC object. Built and booted mps3-an547:picostest 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-08-03 08:49:25 +02:00
*/
if (loadinfo->fdpic)
{
size_t nrels = 0;
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
libs/libc/elf: Publish FDPIC functions as descriptors for dlsym. A module that dlopen()s a library gets back function addresses from dlsym() and calls them. Under FDPIC a bare code address is not enough: the callee needs its own data base as well, so what dlsym() returns has to be a function descriptor. The exported symbol table carries no type information -- symtab_s is a name and a value, and its own comment says typing would have to be added to support anything but function pointers -- so by the time dlsym() is asked there is no way to tell a function from an object. libelf_insertsymtab() is the last point that can: st_info is still in hand there. So an FDPIC object's exported functions are published as the address of a descriptor carved from the module's pool, and dlopen(), dlsym() and the module registry need no knowledge of FDPIC at all. The pool is sized for the dynamic symbol table as well as the relocations, since both can draw from it. That leaves the symbol values themselves, which were wrong for any ET_DYN object. libelf_loadsymtab() adds the symbol's section address to its value, which is right for ET_REL, where the section address is where the section was actually placed and the value is relative to it. In a shared object both are already full link-time addresses, so adding them counts the section twice. It needs translating onto wherever the object was placed instead. Library data is shared between everything that dlopen()s it, because the registry holds one instance per name. Giving each user its own copy would mean teaching the registry about instances, which is a much larger change to shared code; an executable loaded through exec() already gets its own data, since that path loads a fresh copy each time. Built and run on lm3s6965-ek with the examples/elf ROMFS; the FDPIC module continues to load, relocate and call through its own descriptors. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-08-03 11:34:35 +02:00
if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_DYNSYM) &&
shdr->sh_entsize != 0)
libs/libc/elf: Read the dynamic tags an FDPIC object needs. libelf_relocatedyn() reads the handful of DT_* tags it needs to walk the relocation tables and ignores the rest. Three more matter now. DT_PLTGOT is where the object's data base lives. An FDPIC module runs with that in the PIC base register, and every function descriptor built for it names the same base as the one its callee should run with, so without it there is nothing to put in a descriptor's second word. The DT_*_ARRAY tags are the constructor and destructor tables. These are already found through the section headers a few lines further down, and that path is kept, but the dynamic tags are the authoritative copy and an object is not obliged to carry section headers at all. Both paths now translate through libelf_addr(), so they agree on the answer rather than depending on which ran last. The tag values themselves were missing from include/elf.h and are added. Sizing the descriptor pool has to happen here rather than later. R_ARM_FUNCDESC asks the loader to manufacture a descriptor and hand back its address, which means the space must exist by the time the relocation is applied, and by then the segment has been placed. So libelf_elfsize() reserves it behind the writable data, bounded by the relocation count -- one relocation cannot ask for more than one descriptor. That bound has slack in it, but a descriptor is two words and modules are small, which is cheaper than walking every relocation twice to get an exact count. Nothing here runs for a non-FDPIC object. Built and booted mps3-an547:picostest 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-08-03 08:49:25 +02:00
{
nrels += shdr->sh_size / shdr->sh_entsize;
}
}
loadinfo->ndesc = nrels;
datasize += nrels * sizeof(struct fdpic_desc_s);
binfo("fdpic: reserving %zu descriptors behind the data\n", nrels);
}
libs/libc/elf: Give a shared object a word alignment, not zero. libelf_elfsize() takes textalign and dataalign from the section headers, which only the ET_REL path walks. An ET_DYN object is sized from its program headers instead, so both fields stay at zero, and the allocation a few lines later asks for that alignment: loadinfo->textalloc = lib_memalign(loadinfo->textalign, ...); Zero is not a valid alignment, and every path that receives it divides by it. mm_memalign() accepts zero as a power of two, because 0 & -0 is 0, then takes the "alignment <= MM_ALIGN" branch and evaluates "((uintptr_t)ptr) % alignment" in a DEBUGASSERT. With CONFIG_MM_HEAP_MEMPOOL and a pool that fits the request the object never reaches that branch and gets ALIGN_UP(blk, 0) instead, which is ((blk - 1) / 0) * 0. On Cortex-M this is usually invisible: UDIV returns zero for a division by zero unless CCR.DIV_0_TRP is set, which NuttX does not set, so the assertion compares zero against zero and passes. It is a SIGFPE on the simulator, and the mempool path returns a null pointer wherever the division yields zero, which the loader reports as -ENOMEM. Ask for a natural word when the program headers gave nothing. p_align is the linker's page granularity, not a section requirement, so honouring it would cost a page per module for no gain, and the sections of a shared object need no more than a word. Built for mps3-an547:picostest, which is CONFIG_ELF with CONFIG_PIC. Runtime evidence on hardware follows. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-08-23 22:55:59 +02:00
/* An ET_DYN object is sized from its program headers, which give no
* section alignment. A word is enough.
*/
if (loadinfo->textalign == 0)
{
loadinfo->textalign = sizeof(uintptr_t);
}
if (loadinfo->dataalign == 0)
{
loadinfo->dataalign = sizeof(uintptr_t);
}
/* Save the allocation size */
loadinfo->textsize = textsize;
loadinfo->datasize = datasize;
}
#ifdef CONFIG_LIBC_ELF_LOADTO_LMA
/****************************************************************************
* Name: libelf_vma2lma
*
* Description:
* Convert section`s VMA to LMA according to PhysAddr(p_paddr) of
* Program Header.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
static int libelf_vma2lma(FAR struct mod_loadinfo_s *loadinfo,
FAR Elf_Shdr *shdr, FAR Elf_Addr *lma)
{
int i;
for (i = 0; i < loadinfo->ehdr.e_phnum; i++)
{
FAR Elf_Phdr *phdr = &loadinfo->phdr[i];
if (shdr->sh_addr >= phdr->p_vaddr &&
shdr->sh_addr + shdr->sh_size <= phdr->p_vaddr + phdr->p_memsz &&
shdr->sh_offset >= phdr->p_offset &&
shdr->sh_offset <= phdr->p_offset + phdr->p_filesz)
{
*lma = phdr->p_paddr + shdr->sh_addr - phdr->p_vaddr;
return OK;
}
}
return -ENOENT;
}
#endif
/****************************************************************************
* Name: libelf_set_emptysect_vma
*
* Description:
* Set VMA for empty and unallocated sections, some relocations might
* depend on this.
*
* Returned Value:
* None.
*
****************************************************************************/
static void libelf_set_emptysect_vma(FAR struct mod_loadinfo_s *loadinfo,
int section)
{
FAR Elf_Shdr *shdr = &loadinfo->shdr[section];
/* Set the section as data or text, depending on SHF_WRITE */
if ((shdr->sh_flags & SHF_WRITE) != 0
#ifdef CONFIG_ARCH_HAVE_TEXT_HEAP_WORD_ALIGNED_READ
|| (shdr->sh_flags & SHF_EXECINSTR) == 0
#endif
)
{
shdr->sh_addr = loadinfo->datastart;
}
else
{
shdr->sh_addr = loadinfo->textalloc;
}
}
/****************************************************************************
* Name: libelf_loadfile
*
* Description:
* Read the section data into memory. Section addresses in the shdr[] are
* updated to point to the corresponding position in the memory.
*
libs/libc/elf, binfmt: Describe the GOT by base and size, not by index. gotindex named the .got section header, and every user then reached through shdr[] for what it actually wanted. Only one of the five wanted the index. gotbase and gotsize say it directly. gotsize is the extent of .got and is also what says the object has one, and gotbase is where the GOT ended up: the placed address of .got for an ordinary object, or DT_PLTGOT for an FDPIC one, which libelf_bind() already reads. Both are set in libelf_loadfile(), after the sections are placed, so gotbase is the address the object will be read at rather than the one it was linked for. The GOT walk in libelf_loadfile() now runs only when there is a base, which also keeps it off an FDPIC object. An FDPIC object's sections are never placed, so .got carried a link time sh_addr there, and the walk read and wrote through it. Its GOT is relocated through its own relocations. The check that gates libelf_xipacquire() runs before the load, when neither field is set, so it looks the section up by name. It hands the index it found to libelf_loadfile(), which is the only reason that function takes one: the object is searched once, not twice. One behaviour changes: a .got that exists but is empty now reads as no GOT. There is nothing for any of the five users to do with an empty one. Built for pimoroni-pico-2-plus with CONFIG_PIC, CONFIG_ELF and CONFIG_LIBC_ELF, and for mps3-an547:bl, which is the board that read the index. Run on QEMU with mps3-an547:picostest, which loads PIC ELF modules from a romfs: hello prints, and ostest reaches the timed mutex test, the same as before the change. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-09-03 01:00:13 +02:00
* Input Parameters:
* loadinfo - The load state.
* gotidx - Section index of .got, which the caller has already looked
* up, or a negative value if the object has none.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
libs/libc/elf, binfmt: Describe the GOT by base and size, not by index. gotindex named the .got section header, and every user then reached through shdr[] for what it actually wanted. Only one of the five wanted the index. gotbase and gotsize say it directly. gotsize is the extent of .got and is also what says the object has one, and gotbase is where the GOT ended up: the placed address of .got for an ordinary object, or DT_PLTGOT for an FDPIC one, which libelf_bind() already reads. Both are set in libelf_loadfile(), after the sections are placed, so gotbase is the address the object will be read at rather than the one it was linked for. The GOT walk in libelf_loadfile() now runs only when there is a base, which also keeps it off an FDPIC object. An FDPIC object's sections are never placed, so .got carried a link time sh_addr there, and the walk read and wrote through it. Its GOT is relocated through its own relocations. The check that gates libelf_xipacquire() runs before the load, when neither field is set, so it looks the section up by name. It hands the index it found to libelf_loadfile(), which is the only reason that function takes one: the object is searched once, not twice. One behaviour changes: a .got that exists but is empty now reads as no GOT. There is nothing for any of the five users to do with an empty one. Built for pimoroni-pico-2-plus with CONFIG_PIC, CONFIG_ELF and CONFIG_LIBC_ELF, and for mps3-an547:bl, which is the board that read the index. Run on QEMU with mps3-an547:picostest, which loads PIC ELF modules from a romfs: hello prints, and ostest reaches the timed mutex test, the same as before the change. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-09-03 01:00:13 +02:00
static inline int libelf_loadfile(FAR struct mod_loadinfo_s *loadinfo,
int gotidx)
{
FAR uint8_t *text = (FAR uint8_t *)loadinfo->textalloc;
FAR uint8_t *data = (FAR uint8_t *)loadinfo->datastart;
int ret;
int i;
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
/* Read each PT_LOAD area into memory */
binfo("Loading sections - text: %p.%zx data: %p.%zx\n",
text, loadinfo->textsize, data, loadinfo->datasize);
if (loadinfo->ehdr.e_type == ET_DYN)
{
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
for (i = 0; i < loadinfo->ehdr.e_phnum; i++)
{
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
FAR Elf_Phdr *phdr = &loadinfo->phdr[i];
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
if (phdr->p_type == PT_LOAD)
{
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
if (phdr->p_flags & PF_X)
{
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-08-03 00:56:27 +02:00
if (loadinfo->fdpic && loadinfo->xipbase != 0)
{
/* Mapped, not copied. */
continue;
}
ret = libelf_read(loadinfo, buffer_data_address(text),
phdr->p_filesz,
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
phdr->p_offset);
}
else
{
size_t bsssize = phdr->p_memsz - phdr->p_filesz;
ret = libelf_read(loadinfo, data, phdr->p_filesz,
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
phdr->p_offset);
memset(data + phdr->p_filesz, 0, bsssize);
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
}
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
if (ret < 0)
{
berr("ERROR: Failed to read section %d: %d\n", i, ret);
return ret;
}
}
}
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
}
else
{
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
FAR uint8_t **pptr = NULL;
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
/* SHF_ALLOC indicates that the section requires memory during
* execution
*/
if ((shdr->sh_flags & SHF_ALLOC) == 0 || shdr->sh_size == 0)
{
/* Set the VMA regardless */
libelf_set_emptysect_vma(loadinfo, i);
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
continue;
}
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo->ehdr.e_type == ET_REL ||
loadinfo->ehdr.e_type == ET_EXEC)
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
{
pptr = (FAR uint8_t **)&loadinfo->sectalloc[i];
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
}
#endif
if (pptr == NULL)
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
{
/* SHF_WRITE indicates that the section address space is
* writeable
*/
if ((shdr->sh_flags & SHF_WRITE) != 0
#ifdef CONFIG_ARCH_HAVE_TEXT_HEAP_WORD_ALIGNED_READ
|| (shdr->sh_flags & SHF_EXECINSTR) == 0
#endif
)
{
pptr = &data;
}
else
{
pptr = &text;
}
if (loadinfo->xipbase == 0)
{
/* If xipbase is not set, align the address
* xipbase is set, the address can't be aligned
*/
*pptr = (FAR uint8_t *)_ALIGN_UP((uintptr_t)*pptr,
shdr->sh_addralign);
}
}
if ((shdr->sh_flags & SHF_WRITE) == 0 && loadinfo->xipbase != 0)
{
goto skipload;
}
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
/* SHT_NOBITS indicates that there is no data in the file for the
* section.
*/
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
if (shdr->sh_type != SHT_NOBITS)
{
#ifdef CONFIG_LIBC_ELF_LOADTO_LMA
ret = libelf_vma2lma(loadinfo, shdr, (FAR Elf_Addr *)pptr);
if (ret < 0)
{
berr("ERROR: Failed to convert addr %d: %d\n", i, ret);
return ret;
}
#endif
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
/* Read the section data from sh_offset to the memory region */
ret = libelf_read(loadinfo, buffer_data_address(*pptr),
shdr->sh_size, shdr->sh_offset);
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
if (ret < 0)
{
berr("ERROR: Failed to read section %d: %d\n", i, ret);
return ret;
}
}
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
/* If there is no data in an allocated section, then the allocated
* section must be cleared.
*/
#ifndef CONFIG_LIBC_ELF_LOADTO_LMA
else if (*pptr != NULL)
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
{
memset(*pptr, 0, shdr->sh_size);
}
#endif
skipload:
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
/* Update sh_addr to point to copy in memory */
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
binfo("%d. %08lx->%08lx\n", i,
(unsigned long)shdr->sh_addr, (unsigned long)*pptr);
/* Use offset to remember the original file address */
shdr->sh_offset = (uintptr_t)shdr->sh_addr;
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
shdr->sh_addr = (uintptr_t)*pptr;
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo->ehdr.e_type != ET_REL)
{
*pptr += ELF_ALIGNUP(shdr->sh_size);
}
#else
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
/* Setup the memory pointer for the next time through the loop */
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
*pptr += ELF_ALIGNUP(shdr->sh_size);
#endif
}
}
libs/libc/elf, binfmt: Describe the GOT by base and size, not by index. gotindex named the .got section header, and every user then reached through shdr[] for what it actually wanted. Only one of the five wanted the index. gotbase and gotsize say it directly. gotsize is the extent of .got and is also what says the object has one, and gotbase is where the GOT ended up: the placed address of .got for an ordinary object, or DT_PLTGOT for an FDPIC one, which libelf_bind() already reads. Both are set in libelf_loadfile(), after the sections are placed, so gotbase is the address the object will be read at rather than the one it was linked for. The GOT walk in libelf_loadfile() now runs only when there is a base, which also keeps it off an FDPIC object. An FDPIC object's sections are never placed, so .got carried a link time sh_addr there, and the walk read and wrote through it. Its GOT is relocated through its own relocations. The check that gates libelf_xipacquire() runs before the load, when neither field is set, so it looks the section up by name. It hands the index it found to libelf_loadfile(), which is the only reason that function takes one: the object is searched once, not twice. One behaviour changes: a .got that exists but is empty now reads as no GOT. There is nothing for any of the five users to do with an empty one. Built for pimoroni-pico-2-plus with CONFIG_PIC, CONFIG_ELF and CONFIG_LIBC_ELF, and for mps3-an547:bl, which is the board that read the index. Run on QEMU with mps3-an547:picostest, which loads PIC ELF modules from a romfs: hello prints, and ostest reaches the timed mutex test, the same as before the change. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-09-03 01:00:13 +02:00
/* Note the GOT. The sections are placed by now, thus .got carries the
* address it will be read at. An FDPIC object's sections are never
* placed, and libelf_bind() takes its base from DT_PLTGOT instead.
*/
if (gotidx >= 0)
{
loadinfo->gotsize = loadinfo->shdr[gotidx].sh_size;
if (!loadinfo->fdpic)
{
loadinfo->gotbase = loadinfo->shdr[gotidx].sh_addr;
}
}
/* Update GOT table. An FDPIC object's entries are relocated through its
* own relocations, so there is nothing to do for one here.
*/
libs/libc/elf, binfmt: Describe the GOT by base and size, not by index. gotindex named the .got section header, and every user then reached through shdr[] for what it actually wanted. Only one of the five wanted the index. gotbase and gotsize say it directly. gotsize is the extent of .got and is also what says the object has one, and gotbase is where the GOT ended up: the placed address of .got for an ordinary object, or DT_PLTGOT for an FDPIC one, which libelf_bind() already reads. Both are set in libelf_loadfile(), after the sections are placed, so gotbase is the address the object will be read at rather than the one it was linked for. The GOT walk in libelf_loadfile() now runs only when there is a base, which also keeps it off an FDPIC object. An FDPIC object's sections are never placed, so .got carried a link time sh_addr there, and the walk read and wrote through it. Its GOT is relocated through its own relocations. The check that gates libelf_xipacquire() runs before the load, when neither field is set, so it looks the section up by name. It hands the index it found to libelf_loadfile(), which is the only reason that function takes one: the object is searched once, not twice. One behaviour changes: a .got that exists but is empty now reads as no GOT. There is nothing for any of the five users to do with an empty one. Built for pimoroni-pico-2-plus with CONFIG_PIC, CONFIG_ELF and CONFIG_LIBC_ELF, and for mps3-an547:bl, which is the board that read the index. Run on QEMU with mps3-an547:picostest, which loads PIC ELF modules from a romfs: hello prints, and ostest reaches the timed mutex test, the same as before the change. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-09-03 01:00:13 +02:00
if (loadinfo->gotbase != 0)
{
libs/libc/elf, binfmt: Describe the GOT by base and size, not by index. gotindex named the .got section header, and every user then reached through shdr[] for what it actually wanted. Only one of the five wanted the index. gotbase and gotsize say it directly. gotsize is the extent of .got and is also what says the object has one, and gotbase is where the GOT ended up: the placed address of .got for an ordinary object, or DT_PLTGOT for an FDPIC one, which libelf_bind() already reads. Both are set in libelf_loadfile(), after the sections are placed, so gotbase is the address the object will be read at rather than the one it was linked for. The GOT walk in libelf_loadfile() now runs only when there is a base, which also keeps it off an FDPIC object. An FDPIC object's sections are never placed, so .got carried a link time sh_addr there, and the walk read and wrote through it. Its GOT is relocated through its own relocations. The check that gates libelf_xipacquire() runs before the load, when neither field is set, so it looks the section up by name. It hands the index it found to libelf_loadfile(), which is the only reason that function takes one: the object is searched once, not twice. One behaviour changes: a .got that exists but is empty now reads as no GOT. There is nothing for any of the five users to do with an empty one. Built for pimoroni-pico-2-plus with CONFIG_PIC, CONFIG_ELF and CONFIG_LIBC_ELF, and for mps3-an547:bl, which is the board that read the index. Run on QEMU with mps3-an547:picostest, which loads PIC ELF modules from a romfs: hello prints, and ostest reaches the timed mutex test, the same as before the change. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-09-03 01:00:13 +02:00
FAR uintptr_t *got = (FAR uintptr_t *)loadinfo->gotbase;
FAR uintptr_t *end = got + loadinfo->gotsize / sizeof(uintptr_t);
for (; got < end; got++)
{
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
if ((shdr->sh_flags & SHF_ALLOC) == 0)
{
continue;
}
if (*got >= shdr->sh_offset &&
*got < shdr->sh_offset + shdr->sh_size)
{
*got += shdr->sh_addr - shdr->sh_offset;
}
}
}
}
return OK;
}
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-08-03 00:56:27 +02:00
/****************************************************************************
* Name: libelf_xipacquire
*
* Description:
* Ask the filesystem for the address of this file on its media, so the
* read-only part of the object can run where it lies. Ask for a pin
* first: a compacting filesystem is not safe without one. Do not ask at
* all if this build cannot hold a pin.
*
* Returned Value:
* Zero if an address was obtained, a negated errno otherwise. Callers
* that can live without one may ignore the failure.
*
****************************************************************************/
#ifdef HAVE_LIBC_ELF_PIN
static int libelf_pinhold(FAR struct mod_loadinfo_s *loadinfo)
{
FAR struct file *filep;
int ret;
/* The descriptor belongs to the task that called the loader, and the
* unload runs on another task. Hold the file instead.
*/
loadinfo->pinfile = lib_zalloc(sizeof(struct file));
if (loadinfo->pinfile == NULL)
{
return -ENOMEM;
}
ret = file_get(loadinfo->filfd, &filep);
if (ret >= 0)
{
ret = file_dup2(filep, loadinfo->pinfile);
file_put(filep);
}
if (ret < 0)
{
lib_free(loadinfo->pinfile);
loadinfo->pinfile = NULL;
}
return ret;
}
#endif
static int libelf_xipacquire(FAR struct mod_loadinfo_s *loadinfo)
{
uintptr_t base = 0;
#ifdef HAVE_LIBC_ELF_PIN
if (ioctl(loadinfo->filfd, XIPFSIOC_PIN, (unsigned long)&base) >= 0)
{
int ret = libelf_pinhold(loadinfo);
if (ret < 0)
{
berr("ERROR: Failed to hold the pinned file: %d\n", ret);
ioctl(loadinfo->filfd, XIPFSIOC_UNPIN, 0);
return ret;
}
loadinfo->xipbase = base;
binfo("pinned xipbase %" PRIxPTR "\n", loadinfo->xipbase);
return OK;
}
#endif
if (ioctl(loadinfo->filfd, FIOC_XIPBASE, (unsigned long)&base) >= 0)
{
loadinfo->xipbase = base;
binfo("can use xipbase %" PRIxPTR "\n", loadinfo->xipbase);
return OK;
}
return -ENOTTY;
}
/****************************************************************************
* Public Functions
****************************************************************************/
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-08-03 00:56:27 +02:00
#ifdef HAVE_LIBC_ELF_PIN
/****************************************************************************
* Name: libelf_pinrelease
*
* Description:
* Give back an XIP pin and the file it was held through, so the
* filesystem can reclaim the extent.
*
****************************************************************************/
void libelf_pinrelease(FAR struct file **pinfile)
{
if (*pinfile != NULL)
{
file_ioctl(*pinfile, XIPFSIOC_UNPIN, 0);
file_close(*pinfile);
lib_free(*pinfile);
*pinfile = NULL;
}
}
#endif
/****************************************************************************
* Name: libelf_load
*
* Description:
* Loads the binary into memory, allocating memory, performing relocations
* and initializing the data and bss segments.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libelf_load(FAR struct mod_loadinfo_s *loadinfo)
{
libs/libc/elf, binfmt: Describe the GOT by base and size, not by index. gotindex named the .got section header, and every user then reached through shdr[] for what it actually wanted. Only one of the five wanted the index. gotbase and gotsize say it directly. gotsize is the extent of .got and is also what says the object has one, and gotbase is where the GOT ended up: the placed address of .got for an ordinary object, or DT_PLTGOT for an FDPIC one, which libelf_bind() already reads. Both are set in libelf_loadfile(), after the sections are placed, so gotbase is the address the object will be read at rather than the one it was linked for. The GOT walk in libelf_loadfile() now runs only when there is a base, which also keeps it off an FDPIC object. An FDPIC object's sections are never placed, so .got carried a link time sh_addr there, and the walk read and wrote through it. Its GOT is relocated through its own relocations. The check that gates libelf_xipacquire() runs before the load, when neither field is set, so it looks the section up by name. It hands the index it found to libelf_loadfile(), which is the only reason that function takes one: the object is searched once, not twice. One behaviour changes: a .got that exists but is empty now reads as no GOT. There is nothing for any of the five users to do with an empty one. Built for pimoroni-pico-2-plus with CONFIG_PIC, CONFIG_ELF and CONFIG_LIBC_ELF, and for mps3-an547:bl, which is the board that read the index. Run on QEMU with mps3-an547:picostest, which loads PIC ELF modules from a romfs: hello prints, and ostest reaches the timed mutex test, the same as before the change. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-09-03 01:00:13 +02:00
int gotidx;
int ret;
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-08-03 00:56:27 +02:00
int i;
binfo("loadinfo: %p\n", loadinfo);
DEBUGASSERT(loadinfo && loadinfo->filfd >= 0);
Add support for the loading of ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Fix cast of error message parameters * build-globals.sh - Build the modlib_globals.S file used to resolve symbols when dynamically loading * libs/libc/modlib/Make.defs - Build modlib_globals.S for all targets * libs/libc/modlib/modlib_load.c - Calculate sizes and text/data addresses based on program headers rather than section headers - Handle objects with no program headers * libs/libc/modlib/modlib_bind.c - Call modlib_readsym with pointer to symbol table - Add modlib_relocatedyn to manage relocation of symbols with shared object (ET_DYN) - Differentiate between ET_REL and ET_DYN objects - Use arch independent symbol ELF_R_SYM - Cast sizes to avoid warnings * libs/libc/modlib/modlib_load.c - Cast sizes to avoid warnings * include/elf.h - Add definitions that may be found in shared objects * include/nuttx/lib/modlib.h - Add parameter to modlib_readsym prototype - Add prototypes for: - modlib_insertsymtab - modlib_findglobal - Define Elf_Dyn and Elf_Off according to the elf architecture - Add fields to mod_loadifno_s: - Program headers - Exported symbols - Data section address - Padding requirement - Section index for dynamic symbol table - Number of symbols exported - Add prottotype for modlib_freesymtab * libs/libc/dlfcn/lib_dlclose.c - Free the symbol table when the dll is closed * libs/libc/dlfcn/lib_dlopen.c - Add dump of program headers to debug routine - Differentiate between ET_REL and ET_DYN objects * libs/libc/machine/arm/armv7-m/arch_elf.c - Add handling of R_ARM_RELATIVE and R_ARM_JUMP slot relocation types * libs/libc/modlib/modlib_loadshdrs.c - Rename modlib_loadshdrs.c to modlib_loadhdrs.c - Rename modlib_loadshdrs to modlib_loadhdrs - Add code to load program headers * libs/libc/modlib/modlib_symbols.c - Define entry point structure - Add offset parameter to modlib_symname() and use to find symbol names - Add symtab section header parameter to modlib_readsym() - Add offset parameter to modlib_symvalue() to locate symbol names - Add modlib_insertsyntab() to create a symbol table for exporting and resolution - Add findEP() to resolve a symbol in the modlib_global table - Add modlib_findglobal() to find symbol in the modlib_global table - Add modlib_freesymtab() to free the symbol table * libs/libc/modlib/modlib_uninit.c - Free header and sections from a module_loadinfo_s control block * libs/libc/modlib/modlib_verify.c - Handle ET_DYN shared objects * libs/libc/modlib/modlib_globals.S - Multi-target global table - Define library APIs that may be resolved when loading a shared object
2022-09-26 16:22:03 +10:00
/* Load section and program headers into memory */
ret = libelf_loadhdrs(loadinfo);
if (ret < 0)
{
berr("ERROR: libelf_loadhdrs failed: %d\n", ret);
goto errout_with_buffers;
}
libs/libc/elf, binfmt: Describe the GOT by base and size, not by index. gotindex named the .got section header, and every user then reached through shdr[] for what it actually wanted. Only one of the five wanted the index. gotbase and gotsize say it directly. gotsize is the extent of .got and is also what says the object has one, and gotbase is where the GOT ended up: the placed address of .got for an ordinary object, or DT_PLTGOT for an FDPIC one, which libelf_bind() already reads. Both are set in libelf_loadfile(), after the sections are placed, so gotbase is the address the object will be read at rather than the one it was linked for. The GOT walk in libelf_loadfile() now runs only when there is a base, which also keeps it off an FDPIC object. An FDPIC object's sections are never placed, so .got carried a link time sh_addr there, and the walk read and wrote through it. Its GOT is relocated through its own relocations. The check that gates libelf_xipacquire() runs before the load, when neither field is set, so it looks the section up by name. It hands the index it found to libelf_loadfile(), which is the only reason that function takes one: the object is searched once, not twice. One behaviour changes: a .got that exists but is empty now reads as no GOT. There is nothing for any of the five users to do with an empty one. Built for pimoroni-pico-2-plus with CONFIG_PIC, CONFIG_ELF and CONFIG_LIBC_ELF, and for mps3-an547:bl, which is the board that read the index. Run on QEMU with mps3-an547:picostest, which loads PIC ELF modules from a romfs: hello prints, and ostest reaches the timed mutex test, the same as before the change. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-09-03 01:00:13 +02:00
/* An object with a GOT is position independent, thus its read-only part
* may be able to stay where the filesystem holds it. Keep the index:
* libelf_loadfile() notes the section once it has placed it.
*/
gotidx = libelf_findsection(loadinfo, ".got");
if (gotidx >= 0)
{
libs/libc/elf, binfmt: Describe the GOT by base and size, not by index. gotindex named the .got section header, and every user then reached through shdr[] for what it actually wanted. Only one of the five wanted the index. gotbase and gotsize say it directly. gotsize is the extent of .got and is also what says the object has one, and gotbase is where the GOT ended up: the placed address of .got for an ordinary object, or DT_PLTGOT for an FDPIC one, which libelf_bind() already reads. Both are set in libelf_loadfile(), after the sections are placed, so gotbase is the address the object will be read at rather than the one it was linked for. The GOT walk in libelf_loadfile() now runs only when there is a base, which also keeps it off an FDPIC object. An FDPIC object's sections are never placed, so .got carried a link time sh_addr there, and the walk read and wrote through it. Its GOT is relocated through its own relocations. The check that gates libelf_xipacquire() runs before the load, when neither field is set, so it looks the section up by name. It hands the index it found to libelf_loadfile(), which is the only reason that function takes one: the object is searched once, not twice. One behaviour changes: a .got that exists but is empty now reads as no GOT. There is nothing for any of the five users to do with an empty one. Built for pimoroni-pico-2-plus with CONFIG_PIC, CONFIG_ELF and CONFIG_LIBC_ELF, and for mps3-an547:bl, which is the board that read the index. Run on QEMU with mps3-an547:picostest, which loads PIC ELF modules from a romfs: hello prints, and ostest reaches the timed mutex test, the same as before the change. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-09-03 01:00:13 +02:00
binfo("GOT section found! index %d\n", gotidx);
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-08-03 00:56:27 +02:00
libelf_xipacquire(loadinfo);
}
/* Determine total size to allocate */
libelf_elfsize(loadinfo, true);
/* Allocate (and zero) memory for the ELF file. */
/* Allocate memory to hold the ELF image */
/* For Dynamic shared objects the relative positions between
* text and data must be maintained due to references to the
* GOT. Therefore we cannot do two different allocations.
*/
#ifndef CONFIG_LIBC_ELF_LOADTO_LMA
if (loadinfo->ehdr.e_type == ET_REL || loadinfo->ehdr.e_type == ET_EXEC)
{
# ifndef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo->xipbase != 0)
{
loadinfo->textalloc = loadinfo->xipbase +
loadinfo->shdr[1].sh_offset;
}
else if (loadinfo->textsize > 0)
{
# ifdef CONFIG_ARCH_USE_TEXT_HEAP
loadinfo->textalloc = (uintptr_t)
up_textheap_memalign(loadinfo->textalign,
loadinfo->textsize +
loadinfo->segpad);
# else
loadinfo->textalloc = (uintptr_t)lib_memalign(loadinfo->textalign,
loadinfo->textsize +
loadinfo->segpad);
# endif
if (!loadinfo->textalloc)
{
berr("ERROR: Failed to allocate memory for the module text\n");
ret = -ENOMEM;
goto errout_with_buffers;
}
}
if (loadinfo->datasize > 0)
{
# ifdef CONFIG_ARCH_USE_DATA_HEAP
loadinfo->datastart = (uintptr_t)
up_dataheap_memalign(loadinfo->dataalign,
loadinfo->datasize);
# else
loadinfo->datastart = (uintptr_t)lib_memalign(loadinfo->dataalign,
loadinfo->datasize);
# endif
if (!loadinfo->datastart)
{
berr("ERROR: Failed to allocate memory for the module data\n");
ret = -ENOMEM;
goto errout_with_buffers;
}
}
# endif
}
else if (loadinfo->ehdr.e_type == ET_DYN)
{
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-08-03 00:56:27 +02:00
if (loadinfo->fdpic)
{
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-08-03 00:56:27 +02:00
/* The two segments are placed independently, thus only the
* writable segment is allocated, once per instance.
*/
if (loadinfo->xipbase != 0)
{
/* The text stays on the media. The media address is the base
* of the file, thus add the file offset of the segment.
*/
for (i = 0; i < loadinfo->ehdr.e_phnum; i++)
{
FAR Elf_Phdr *phdr = &loadinfo->phdr[i];
if (phdr->p_type == PT_LOAD &&
(phdr->p_flags & PF_X) != 0)
{
loadinfo->textalloc = loadinfo->xipbase +
phdr->p_offset;
break;
}
}
}
else if (loadinfo->textsize > 0)
{
/* The filesystem cannot show its media, thus copy the text
* to RAM. The instances no longer share it.
*/
# if defined(CONFIG_ARCH_USE_TEXT_HEAP) && \
defined(CONFIG_ARCH_USE_SEPARATED_SECTION)
loadinfo->textalloc = (uintptr_t)
up_textheap_memalign(".text",
loadinfo->textalign,
loadinfo->textsize);
# elif defined(CONFIG_ARCH_USE_TEXT_HEAP)
loadinfo->textalloc = (uintptr_t)
up_textheap_memalign(loadinfo->textalign,
loadinfo->textsize);
# else
loadinfo->textalloc = (uintptr_t)
lib_memalign(loadinfo->textalign,
loadinfo->textsize);
# endif
if (loadinfo->textalloc == 0)
{
berr("ERROR: Failed to allocate the module's text\n");
ret = -ENOMEM;
goto errout_with_buffers;
}
}
if (loadinfo->datasize > 0)
{
loadinfo->datastart =
(uintptr_t)lib_memalign(loadinfo->dataalign,
loadinfo->datasize);
if (!loadinfo->datastart)
{
berr("ERROR: Failed to allocate the module's data\n");
ret = -ENOMEM;
goto errout_with_buffers;
}
}
libs/libc/elf: Read the dynamic tags an FDPIC object needs. libelf_relocatedyn() reads the handful of DT_* tags it needs to walk the relocation tables and ignores the rest. Three more matter now. DT_PLTGOT is where the object's data base lives. An FDPIC module runs with that in the PIC base register, and every function descriptor built for it names the same base as the one its callee should run with, so without it there is nothing to put in a descriptor's second word. The DT_*_ARRAY tags are the constructor and destructor tables. These are already found through the section headers a few lines further down, and that path is kept, but the dynamic tags are the authoritative copy and an object is not obliged to carry section headers at all. Both paths now translate through libelf_addr(), so they agree on the answer rather than depending on which ran last. The tag values themselves were missing from include/elf.h and are added. Sizing the descriptor pool has to happen here rather than later. R_ARM_FUNCDESC asks the loader to manufacture a descriptor and hand back its address, which means the space must exist by the time the relocation is applied, and by then the segment has been placed. So libelf_elfsize() reserves it behind the writable data, bounded by the relocation count -- one relocation cannot ask for more than one descriptor. That bound has slack in it, but a descriptor is two words and modules are small, which is cheaper than walking every relocation twice to get an exact count. Nothing here runs for a non-FDPIC object. Built and booted mps3-an547:picostest 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-08-03 08:49:25 +02:00
/* The pool was reserved at the end of the segment when it was
* sized, so it starts that many descriptors back from the end.
*/
loadinfo->descpool = (FAR struct fdpic_desc_s *)
(loadinfo->datastart + loadinfo->datasize) -
loadinfo->ndesc;
}
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-08-03 00:56:27 +02:00
else
{
/* Everything else keeps text and data adjacent: one allocation,
* data behind text.
*/
loadinfo->textalloc = (uintptr_t)
lib_memalign(loadinfo->textalign,
loadinfo->textsize +
loadinfo->datasize +
loadinfo->segpad);
if (!loadinfo->textalloc)
{
berr("ERROR: Failed to allocate memory for the module\n");
ret = -ENOMEM;
goto errout_with_buffers;
}
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-08-03 00:56:27 +02:00
loadinfo->datastart = loadinfo->textalloc +
loadinfo->textsize +
loadinfo->segpad;
}
}
#endif /* CONFIG_LIBC_ELF_LOADTO_LMA */
/* Load ELF section data into memory */
libs/libc/elf, binfmt: Describe the GOT by base and size, not by index. gotindex named the .got section header, and every user then reached through shdr[] for what it actually wanted. Only one of the five wanted the index. gotbase and gotsize say it directly. gotsize is the extent of .got and is also what says the object has one, and gotbase is where the GOT ended up: the placed address of .got for an ordinary object, or DT_PLTGOT for an FDPIC one, which libelf_bind() already reads. Both are set in libelf_loadfile(), after the sections are placed, so gotbase is the address the object will be read at rather than the one it was linked for. The GOT walk in libelf_loadfile() now runs only when there is a base, which also keeps it off an FDPIC object. An FDPIC object's sections are never placed, so .got carried a link time sh_addr there, and the walk read and wrote through it. Its GOT is relocated through its own relocations. The check that gates libelf_xipacquire() runs before the load, when neither field is set, so it looks the section up by name. It hands the index it found to libelf_loadfile(), which is the only reason that function takes one: the object is searched once, not twice. One behaviour changes: a .got that exists but is empty now reads as no GOT. There is nothing for any of the five users to do with an empty one. Built for pimoroni-pico-2-plus with CONFIG_PIC, CONFIG_ELF and CONFIG_LIBC_ELF, and for mps3-an547:bl, which is the board that read the index. Run on QEMU with mps3-an547:picostest, which loads PIC ELF modules from a romfs: hello prints, and ostest reaches the timed mutex test, the same as before the change. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-09-03 01:00:13 +02:00
ret = libelf_loadfile(loadinfo, gotidx);
if (ret < 0)
{
berr("ERROR: libelf_loadfile failed: %d\n", ret);
goto errout_with_buffers;
}
#ifdef CONFIG_LIBC_ELF_EXIDX_SECTNAME
ret = libelf_findsection(loadinfo, CONFIG_LIBC_ELF_EXIDX_SECTNAME);
if (ret < 0)
{
binfo("libelf_findsection: Exception Index section not found: %d\n",
ret);
}
else
{
up_init_exidx(loadinfo->shdr[ret].sh_addr,
loadinfo->shdr[ret].sh_size);
}
#endif
return OK;
/* Error exits */
errout_with_buffers:
libelf_unload(loadinfo);
return ret;
}
/****************************************************************************
* Name: libelf_load_with_addrenv
*
* Description:
* Loads the binary into memory, use the address environment to load the
* binary.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV
int libelf_load_with_addrenv(FAR struct mod_loadinfo_s *loadinfo)
{
libs/libc/elf, binfmt: Describe the GOT by base and size, not by index. gotindex named the .got section header, and every user then reached through shdr[] for what it actually wanted. Only one of the five wanted the index. gotbase and gotsize say it directly. gotsize is the extent of .got and is also what says the object has one, and gotbase is where the GOT ended up: the placed address of .got for an ordinary object, or DT_PLTGOT for an FDPIC one, which libelf_bind() already reads. Both are set in libelf_loadfile(), after the sections are placed, so gotbase is the address the object will be read at rather than the one it was linked for. The GOT walk in libelf_loadfile() now runs only when there is a base, which also keeps it off an FDPIC object. An FDPIC object's sections are never placed, so .got carried a link time sh_addr there, and the walk read and wrote through it. Its GOT is relocated through its own relocations. The check that gates libelf_xipacquire() runs before the load, when neither field is set, so it looks the section up by name. It hands the index it found to libelf_loadfile(), which is the only reason that function takes one: the object is searched once, not twice. One behaviour changes: a .got that exists but is empty now reads as no GOT. There is nothing for any of the five users to do with an empty one. Built for pimoroni-pico-2-plus with CONFIG_PIC, CONFIG_ELF and CONFIG_LIBC_ELF, and for mps3-an547:bl, which is the board that read the index. Run on QEMU with mps3-an547:picostest, which loads PIC ELF modules from a romfs: hello prints, and ostest reaches the timed mutex test, the same as before the change. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-09-03 01:00:13 +02:00
int gotidx;
int ret;
binfo("loadinfo: %p\n", loadinfo);
DEBUGASSERT(loadinfo && loadinfo->filfd >= 0);
/* Load section and program headers into memory */
ret = libelf_loadhdrs(loadinfo);
if (ret < 0)
{
berr("ERROR: libelf_loadhdrs failed: %d\n", ret);
goto errout_with_buffers;
}
libs/libc/elf, binfmt: Describe the GOT by base and size, not by index. gotindex named the .got section header, and every user then reached through shdr[] for what it actually wanted. Only one of the five wanted the index. gotbase and gotsize say it directly. gotsize is the extent of .got and is also what says the object has one, and gotbase is where the GOT ended up: the placed address of .got for an ordinary object, or DT_PLTGOT for an FDPIC one, which libelf_bind() already reads. Both are set in libelf_loadfile(), after the sections are placed, so gotbase is the address the object will be read at rather than the one it was linked for. The GOT walk in libelf_loadfile() now runs only when there is a base, which also keeps it off an FDPIC object. An FDPIC object's sections are never placed, so .got carried a link time sh_addr there, and the walk read and wrote through it. Its GOT is relocated through its own relocations. The check that gates libelf_xipacquire() runs before the load, when neither field is set, so it looks the section up by name. It hands the index it found to libelf_loadfile(), which is the only reason that function takes one: the object is searched once, not twice. One behaviour changes: a .got that exists but is empty now reads as no GOT. There is nothing for any of the five users to do with an empty one. Built for pimoroni-pico-2-plus with CONFIG_PIC, CONFIG_ELF and CONFIG_LIBC_ELF, and for mps3-an547:bl, which is the board that read the index. Run on QEMU with mps3-an547:picostest, which loads PIC ELF modules from a romfs: hello prints, and ostest reaches the timed mutex test, the same as before the change. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-09-03 01:00:13 +02:00
/* An object with a GOT is position independent, thus its read-only part
* may be able to stay where the filesystem holds it. Keep the index:
* libelf_loadfile() notes the section once it has placed it.
*/
gotidx = libelf_findsection(loadinfo, ".got");
if (gotidx >= 0)
{
libs/libc/elf, binfmt: Describe the GOT by base and size, not by index. gotindex named the .got section header, and every user then reached through shdr[] for what it actually wanted. Only one of the five wanted the index. gotbase and gotsize say it directly. gotsize is the extent of .got and is also what says the object has one, and gotbase is where the GOT ended up: the placed address of .got for an ordinary object, or DT_PLTGOT for an FDPIC one, which libelf_bind() already reads. Both are set in libelf_loadfile(), after the sections are placed, so gotbase is the address the object will be read at rather than the one it was linked for. The GOT walk in libelf_loadfile() now runs only when there is a base, which also keeps it off an FDPIC object. An FDPIC object's sections are never placed, so .got carried a link time sh_addr there, and the walk read and wrote through it. Its GOT is relocated through its own relocations. The check that gates libelf_xipacquire() runs before the load, when neither field is set, so it looks the section up by name. It hands the index it found to libelf_loadfile(), which is the only reason that function takes one: the object is searched once, not twice. One behaviour changes: a .got that exists but is empty now reads as no GOT. There is nothing for any of the five users to do with an empty one. Built for pimoroni-pico-2-plus with CONFIG_PIC, CONFIG_ELF and CONFIG_LIBC_ELF, and for mps3-an547:bl, which is the board that read the index. Run on QEMU with mps3-an547:picostest, which loads PIC ELF modules from a romfs: hello prints, and ostest reaches the timed mutex test, the same as before the change. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-09-03 01:00:13 +02:00
binfo("GOT section found! index %d\n", gotidx);
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-08-03 00:56:27 +02:00
libelf_xipacquire(loadinfo);
}
/* Determine total size to allocate */
libelf_elfsize(loadinfo, false);
ret = libelf_addrenv_alloc(loadinfo, loadinfo->textsize,
loadinfo->datasize);
if (ret < 0)
{
berr("ERROR: Failed to create address environment: %d\n", ret);
goto errout_with_buffers;
}
/* If CONFIG_ARCH_ADDRENV=y, then the loaded ELF lies in a virtual address
* space that may not be in place now. elf_addrenv_select() will
* temporarily instantiate that address space.
*/
ret = libelf_addrenv_select(loadinfo);
if (ret < 0)
{
berr("ERROR: elf_addrenv_select() failed: %d\n", ret);
goto errout_with_buffers;
}
libs/libc/elf, binfmt: Describe the GOT by base and size, not by index. gotindex named the .got section header, and every user then reached through shdr[] for what it actually wanted. Only one of the five wanted the index. gotbase and gotsize say it directly. gotsize is the extent of .got and is also what says the object has one, and gotbase is where the GOT ended up: the placed address of .got for an ordinary object, or DT_PLTGOT for an FDPIC one, which libelf_bind() already reads. Both are set in libelf_loadfile(), after the sections are placed, so gotbase is the address the object will be read at rather than the one it was linked for. The GOT walk in libelf_loadfile() now runs only when there is a base, which also keeps it off an FDPIC object. An FDPIC object's sections are never placed, so .got carried a link time sh_addr there, and the walk read and wrote through it. Its GOT is relocated through its own relocations. The check that gates libelf_xipacquire() runs before the load, when neither field is set, so it looks the section up by name. It hands the index it found to libelf_loadfile(), which is the only reason that function takes one: the object is searched once, not twice. One behaviour changes: a .got that exists but is empty now reads as no GOT. There is nothing for any of the five users to do with an empty one. Built for pimoroni-pico-2-plus with CONFIG_PIC, CONFIG_ELF and CONFIG_LIBC_ELF, and for mps3-an547:bl, which is the board that read the index. Run on QEMU with mps3-an547:picostest, which loads PIC ELF modules from a romfs: hello prints, and ostest reaches the timed mutex test, the same as before the change. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-09-03 01:00:13 +02:00
ret = libelf_loadfile(loadinfo, gotidx);
if (ret < 0)
{
berr("ERROR: libelf_loadfile failed: %d\n", ret);
goto errout_with_addrenv;
}
/* Restore the original address environment */
ret = libelf_addrenv_restore(loadinfo);
if (ret < 0)
{
berr("ERROR: libelf_addrenv_restore() failed: %d\n", ret);
goto errout_with_buffers;
}
return OK;
errout_with_addrenv:
libelf_addrenv_restore(loadinfo);
errout_with_buffers:
libelf_unload(loadinfo);
return ret;
}
#endif