libs/libc/modlib: fix dynamic loader issues

* build-globals.sh
    - Macros for defining symbols etc. based on assembler in use
    - Use the System.map to get all the nuttx symbols

  * libs/libc/modlib/modlib_globals.S
    - Provide an empty skeleton. If the dynamic loading functions
      are required then run build-global.sh after a clean build
      using the skeleton. This will fill out the skeleton with the
      symbols to be available to dynamically loaded modules.

  * libs/libc/modlib/modlib_loadhdrs.c
    - Fix case where there are no program headers are avaiable
This commit is contained in:
Neale Ferguson
2023-07-07 09:15:59 +10:00
committed by David Sidrane
parent a5d1d2d4e5
commit b5cd7c2a82
8 changed files with 185 additions and 4015 deletions
+84 -41
View File
@@ -13,6 +13,8 @@ findEP()
SIZE=${#SYM[@]} SIZE=${#SYM[@]}
L=0 L=0
R=$((SIZE - 1)) R=$((SIZE - 1))
OLDL=99999999
OLDR=99999999
while [ ${L} -le ${R} ] while [ ${L} -le ${R} ]
do do
T=$(( L + R )) T=$(( L + R ))
@@ -26,6 +28,11 @@ findEP()
else else
R=$(( M - 1 )) R=$(( M - 1 ))
fi fi
if [ ${OLDL} -eq ${L} -a ${OLDR} -eq ${R} ]; then
: return 0
fi
OLDL=${L}
OLDR=${R}
done done
return 0 return 0
} }
@@ -38,30 +45,36 @@ getEP()
{ {
for ((i = 0; i < ${#OBJ[@]}; i++)) for ((i = 0; i < ${#OBJ[@]}; i++))
do do
FUNCS=`${NM} -g --defined-only ../staging/${OBJ[$i]} | awk '{print $3}' | sort | grep -Ev ${FILTER}` if [ -f staging/${OBJ[$i]} ]; then
FUNC=(${FUNCS}) FUNCS=`${NM} -g --defined-only staging/${OBJ[$i]} 2>/dev/null | grep "^0" | awk '{print $3}' | sort | grep -Ev ${FILTER}`
for ((j = 0; j < ${#FUNC[@]}; j++)) FUNC=(${FUNCS})
do for ((j = 0; j < ${#FUNC[@]}; j++))
findEP ${FUNC[$j]} do
if [ $? -eq 1 ]; then findEP ${FUNC[$j]}
EP[${I_EP}]=${FUNC[$j]} if [ $? -eq 1 ]; then
I_EP=$((I_EP + 1)) EP[${I_EP}]=${FUNC[$j]}
fi I_EP=$((I_EP + 1))
done fi
done
fi
done done
} }
# #
# Symbols to ignore within the NuttX libraries # Symbols to ignore within the NuttX libraries
# #
FILTER="^lib_low|^FUNCTION|^STUB|^__start|^_vect|^arm_|^arp_|^bch|^binfmt|^blake|^block_|^cdcacm|^chksum|^clock_|^close_|^crypto_|^devif_|^devnull|^devuran|^devzero|^emerg|^epoll_|^elf_|^_dbgR|^dq_|^env_|^file_|^files_|^fs_|^ftl_|^g_|^get_|^group_|^global|^hcom|^i2c_|^inode_|^iob_|^irq_|^kmm_|^lfs_|^lib_|^local_|^mm_|^modlib_|^mpu_|^mq_|^nGlobals|^net_|^netdev_|^nx|^pipecommon|^posix_spawn_file|^psock_|^ramlog|^rammap|^readline_|^register_|^sched_|^sockfd|^spawn_|^sq_|^stm32|^symtab_|^syslog_|^syslogstream|^task_|^tcp_|^timer_|^uart_|^ub[12]|^udp_|^umm_|^umount|^unload_|^unregister|^up_|^usb|^usrsock_|^watchdog|^wd_" FILTER="^lib_low|^FUNCTION|^STUB|^__start|^_vect|^arm_|^arp_|^bch|^binfmt|^blake|^block_|^cdcacm|^chksum|^clock_|^close_|^crypto_|^devif_|^devnull|^devuran|^devzero|^emerg|^epoll_|^elf_|^_dbgR|^dq_|^env_|^file_|^files_|^fs_|^ftl_|^g_|^get_|^group_|^global|^hcom|^i2c_|^inode_|^iob_|^irq_|^kmm_|^lfs_|^lib_|^local_|^mm_|^modlib_|^mpu_|^mq_|^nGlobals|^net_|^netdev_|^nx|^pipecommon|^posix_spawn_file|^psock_|^ramlog|^rammap|^readline_|^register_|^sched_|^sockfd|^spawn_|^sq_|^stm32|^symtab_|^syslog_|^syslogstream|^task_|^tcp_|^timer_|^uart_|^ub[12]|^udp_|^umm_|^umount|^unload_|^unregister|^up_|^usb|^usrsock_|^watchdog|^wd_|globalNames$|nGlobals$|globalTable$|^\.l"
if [ -z "${NM}" ]; then
NM="nm"
fi
# #
# Extract symbols from the runtime # Extract symbols from the runtime
# #
SYMS=`${NM} ../nuttx | awk '{print $3}' | sort | grep -Ev ${FILTER}` SYMS=`cat System.map | awk '{print $3}' | sort | grep -Ev ${FILTER}`
SYM=(${SYMS}) SYM=(${SYMS})
GLOBALS="../libs/libc/modlib/modlib_globals.S" GLOBALS="libs/libc/modlib/modlib_globals.S"
I_EP=0 I_EP=0
# #
@@ -80,70 +93,100 @@ EP=(${EPS})
# #
# Generate the modlib_xxxx_globals.S file # Generate the modlib_xxxx_globals.S file
# #
GLOBALS="libs/libc/modlib/modlib_${arch}_globals.S"
cat >${GLOBALS} <<__EOF__ cat >${GLOBALS} <<__EOF__
#ifdef __CYGWIN__
# define SYMBOL(s) _##s
# define WEAK .weak
# define GLOBAL .global
# define SECTION .data
.macro GLOBAL ep
.global SYMBOL(\ep)
.type SYMBOL(\ep), "object"
.endm
.macro SIZE ep
.endm
#elif defined(__ELF__)
# define SYMBOL(s) s
# define WEAK .weak
# define SECTION .data
.macro GLOBAL ep
.global SYMBOL(\ep)
.type SYMBOL(\ep), "object"
.endm
.macro SIZE ep
.size SYMBOL(\ep), . - SYMBOL(\ep)
.endm
#else
# define SYMBOL(s) _##s
# define WEAK .weak_definition
# define SECTION .section __DATA,__data
.macro GLOBAL ep
.private_extern SYMBOL(\ep)
.globl SYMBOL(\ep)
.endm
.macro SIZE ep
.endm
#endif
#if __SIZEOF_POINTER__ == 8 #if __SIZEOF_POINTER__ == 8
.macro globalEntry index, ep .macro globalEntry index, ep
.weak \p WEAK SYMBOL(\ep)
.quad .L\index .quad .l\index
.quad \ep .quad \ep
.endm .endm
# define ALIGN 8 # define ALIGN 8
#else #else
.macro globalEntry index, ep .macro globalEntry index, ep
.weak \ep WEAK SYMBOL(\ep)
.long .L\index .long .l\index
.long \ep .long \ep
.endm .endm
# define ALIGN 4 # define ALIGN 4
#endif #endif
#ifdef __ARM_ARCH_ISA_THUMB2 #ifdef __ARM_ARCH_ISA_THUMB2
# ifdef __ARM_ARCH_7M__ # ifdef __ARM_ARCH_7M__
.arch armv7e-m .arch armv7e-m
# elif defined ___ARM_ARCH 8 # elif defined ___ARM_ARCH 8
.arch armv8-m.base .arch armv8-m.base
#endif #endif
#ifdef __ARM_ASM_SYNTAX_UNIFIED__ #ifdef __ARM_ASM_SYNTAX_UNIFIED__
.syntax unified .syntax unified
#endif #endif
.thumb .thumb
#endif #endif
.data .data
.align ALIGN .align ALIGN
.global globalNames GLOBAL globalNames
globalNames: SYMBOL(globalNames):
__EOF__ __EOF__
for ((i = 0; i < ${#EP[@]}; i++)) for ((i = 0; i < ${#EP[@]}; i++))
do do
echo ".L${i}: .string \"${EP[$i]}\"" >>${GLOBALS} echo ".l${i}: .string \"${EP[$i]}\"" >>${GLOBALS}
done done
cat >>${GLOBALS} <<__EOF__ cat >>${GLOBALS} <<__EOF__
.size globalNames, . - globalNames SIZE globalNames
.align ${ALIGN} .align ALIGN
.global nGlobals GLOBAL nGlobals
.type nGlobals, "object" SYMBOL(nGlobals):
nGlobals:
.word ${#EP[@]} .word ${#EP[@]}
.size nGlobals, . - nGlobals SIZE nGlobals
.align ${ALIGN} .align ALIGN
.global globalTable GLOBAL globalTable
.type globalTable, "object" SYMBOL(globalTable):
globalTable:
__EOF__ __EOF__
for ((i = 0; i < ${#EP[@]}; i++)) for ((i = 0; i < ${#EP[@]}; i++))
do do
echo " globalEntry ${i}, ${EP[$i]}" >>${GLOBALS} echo " globalEntry ${i}, ${EP[$i]}" >>${GLOBALS}
done done
cat >>${GLOBALS} <<__EOF__ cat >>${GLOBALS} <<__EOF__
.size globalTable, . - globalTable SIZE globalTable
__EOF__ __EOF__
done
echo "${#EP[@]} symbols defined" echo "${#EP[@]} symbols defined"
+3 -7
View File
@@ -493,14 +493,10 @@ int up_relocate(const Elf32_Rel *rel, const Elf32_Sym *sym, uintptr_t addr)
} }
break; break;
case R_ARM_RELATIVE : case R_ARM_RELATIVE:
case R_ARM_JUMP_SLOT : case R_ARM_JUMP_SLOT:
{ {
binfo("Relocating: RELATIVE/JUMP_SLOT at %p value: %08lx" *(uint32_t *)addr = (uint32_t)sym->st_value;
"with %08lx\n",
(void *)addr, *(unsigned long *)addr,
(unsigned long)sym->st_value);
*(uint32_t *) addr = (uint32_t) sym->st_value;
} }
break; break;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+35 -36
View File
@@ -70,14 +70,6 @@ int modlib_loadhdrs(FAR struct mod_loadinfo_s *loadinfo)
return -EINVAL; return -EINVAL;
} }
/* Verify that there are program headers */
if (loadinfo->ehdr.e_phnum < 1)
{
berr("ERROR: No program headers(?)\n");
return -EINVAL;
}
/* Get the total size of the section header table */ /* Get the total size of the section header table */
shdrsize = (size_t)loadinfo->ehdr.e_shentsize * shdrsize = (size_t)loadinfo->ehdr.e_shentsize *
@@ -88,19 +80,9 @@ int modlib_loadhdrs(FAR struct mod_loadinfo_s *loadinfo)
return -ESPIPE; return -ESPIPE;
} }
/* Get the total size of the program header table */
phdrsize = (size_t)loadinfo->ehdr.e_phentsize *
(size_t)loadinfo->ehdr.e_phnum;
if (loadinfo->ehdr.e_phoff + phdrsize > loadinfo->filelen)
{
berr("ERROR: Insufficent space in file for program header table\n");
return -ESPIPE;
}
/* Allocate memory to hold a working copy of the sector header table */ /* Allocate memory to hold a working copy of the sector header table */
loadinfo->shdr = (FAR FAR Elf_Shdr *)lib_malloc(shdrsize); loadinfo->shdr = (FAR Elf_Shdr *)lib_malloc(shdrsize);
if (!loadinfo->shdr) if (!loadinfo->shdr)
{ {
berr("ERROR: Failed to allocate the section header table. Size: %ld\n", berr("ERROR: Failed to allocate the section header table. Size: %ld\n",
@@ -117,26 +99,43 @@ int modlib_loadhdrs(FAR struct mod_loadinfo_s *loadinfo)
berr("ERROR: Failed to read section header table: %d\n", ret); berr("ERROR: Failed to read section header table: %d\n", ret);
} }
/* Allocate memory to hold a working copy of the program header table */ if (loadinfo->ehdr.e_phnum > 0)
loadinfo->phdr = (FAR FAR Elf_Phdr *)lib_malloc(phdrsize);
if (!loadinfo->shdr)
{ {
lib_free((FAR void *)loadinfo->shdr); /* Get the total size of the program header table */
berr("ERROR: Failed to allocate the program header table. Size: %ld\n",
(long)phdrsize); phdrsize = (size_t)loadinfo->ehdr.e_phentsize *
return -ENOMEM; (size_t)loadinfo->ehdr.e_phnum;
if (loadinfo->ehdr.e_phoff + phdrsize > loadinfo->filelen)
{
berr("ERROR: Insufficent space for program header table\n");
return -ESPIPE;
}
/* Allocate memory to hold a working copy of the program header table */
loadinfo->phdr = (FAR Elf_Phdr *)lib_malloc(phdrsize);
if (!loadinfo->phdr)
{
lib_free((FAR void *)loadinfo->shdr);
berr("ERROR: Failed to allocate the program header table."
"Size: %ld\n", (long)phdrsize);
return -ENOMEM;
}
/* Read the program header table into memory */
ret = modlib_read(loadinfo, (FAR uint8_t *)loadinfo->phdr, phdrsize,
loadinfo->ehdr.e_phoff);
if (ret < 0)
{
berr("ERROR: Failed to read program header table: %d\n", ret);
lib_free((FAR void *)loadinfo->phdr);
lib_free((FAR void *)loadinfo->shdr);
}
} }
else
/* Read the program header table into memory */
ret = modlib_read(loadinfo, (FAR uint8_t *)loadinfo->phdr, phdrsize,
loadinfo->ehdr.e_phoff);
if (ret < 0)
{ {
berr("ERROR: Failed to read program header table: %d\n", ret); loadinfo->phdr = NULL;
lib_free((FAR void *)loadinfo->phdr);
lib_free((FAR void *)loadinfo->shdr);
} }
return ret; return ret;
+5 -5
View File
@@ -80,11 +80,11 @@ int modlib_verifyheader(FAR const Elf_Ehdr *ehdr)
if (ehdr->e_type != ET_REL) if (ehdr->e_type != ET_REL)
{ {
if (ehdr->e_type != ET_DYN) if (ehdr->e_type != ET_DYN)
{ {
berr("ERROR: Not a relocatable file: e_type=%d\n", ehdr->e_type); berr("ERROR: Not a relocatable file: e_type=%d\n", ehdr->e_type);
return -EINVAL; return -EINVAL;
} }
} }
/* Verify that this file works with the currently configured architecture */ /* Verify that this file works with the currently configured architecture */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff