From e448443e95392201c3b10de72c697f59bc82aa7a Mon Sep 17 00:00:00 2001 From: Hubert Badocha Date: Tue, 22 Oct 2024 13:06:07 +0200 Subject: [PATCH] process: unify load on NOMMU JIRA: RTOS-958 --- hal/armv7m/arch/elf.h | 24 ++++++++ hal/armv8m/arch/elf.h | 24 ++++++++ hal/armv8r/arch/elf.h | 24 ++++++++ hal/elf.h | 32 ++++++++++ hal/sparcv8leon3/arch/elf.h | 22 +++++++ proc/elf.h | 6 -- proc/process.c | 115 +++++++++++++++--------------------- 7 files changed, 174 insertions(+), 73 deletions(-) create mode 100644 hal/armv7m/arch/elf.h create mode 100644 hal/armv8m/arch/elf.h create mode 100644 hal/armv8r/arch/elf.h create mode 100644 hal/elf.h create mode 100644 hal/sparcv8leon3/arch/elf.h diff --git a/hal/armv7m/arch/elf.h b/hal/armv7m/arch/elf.h new file mode 100644 index 000000000..bd3ea8ce9 --- /dev/null +++ b/hal/armv7m/arch/elf.h @@ -0,0 +1,24 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * Hardware Abstraction Layer ELF support + * + * Copyright 2024 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + +#define R_ARM_ABS32 2 +#define R_ARM_TARGET1 38 + + +static inline int hal_isRelReloc(int relType) +{ + return (relType == R_ARM_ABS32) || (relType == R_ARM_TARGET1); +} diff --git a/hal/armv8m/arch/elf.h b/hal/armv8m/arch/elf.h new file mode 100644 index 000000000..bd3ea8ce9 --- /dev/null +++ b/hal/armv8m/arch/elf.h @@ -0,0 +1,24 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * Hardware Abstraction Layer ELF support + * + * Copyright 2024 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + +#define R_ARM_ABS32 2 +#define R_ARM_TARGET1 38 + + +static inline int hal_isRelReloc(int relType) +{ + return (relType == R_ARM_ABS32) || (relType == R_ARM_TARGET1); +} diff --git a/hal/armv8r/arch/elf.h b/hal/armv8r/arch/elf.h new file mode 100644 index 000000000..bd3ea8ce9 --- /dev/null +++ b/hal/armv8r/arch/elf.h @@ -0,0 +1,24 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * Hardware Abstraction Layer ELF support + * + * Copyright 2024 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + +#define R_ARM_ABS32 2 +#define R_ARM_TARGET1 38 + + +static inline int hal_isRelReloc(int relType) +{ + return (relType == R_ARM_ABS32) || (relType == R_ARM_TARGET1); +} diff --git a/hal/elf.h b/hal/elf.h new file mode 100644 index 000000000..98e7490f4 --- /dev/null +++ b/hal/elf.h @@ -0,0 +1,32 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * Hardware Abstraction Layer ELF support + * + * Copyright 2024 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _HAL_ELF_H_ +#define _HAL_ELF_H_ + + +#ifdef NOMMU + + +#include + + +static int hal_isRelReloc(int relType); + + +#endif + + +#endif diff --git a/hal/sparcv8leon3/arch/elf.h b/hal/sparcv8leon3/arch/elf.h new file mode 100644 index 000000000..e81471101 --- /dev/null +++ b/hal/sparcv8leon3/arch/elf.h @@ -0,0 +1,22 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * Hardware Abstraction Layer ELF support + * + * Copyright 2024 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#define R_SPARC_32 3 + + +static inline int hal_isRelReloc(int relType) +{ + return (relType == R_SPARC_32); +} diff --git a/proc/elf.h b/proc/elf.h index e0b8bbbe7..55382d1b3 100644 --- a/proc/elf.h +++ b/proc/elf.h @@ -180,10 +180,4 @@ typedef struct { #define ELF32_R_INFO(sym, type) (((sym)<<8)+(unsigned char)(type)) -#define R_ARM_ABS32 2 -#define R_ARM_GOT_BREL 26 -#define R_ARM_TARGET1 38 -#define R_SPARC_32 3 - - #endif diff --git a/proc/process.c b/proc/process.c index 19314efac..71de3c737 100644 --- a/proc/process.c +++ b/proc/process.c @@ -15,6 +15,7 @@ */ #include "hal/hal.h" +#include "hal/elf.h" #include "include/errno.h" #include "include/signal.h" #include "vm/vm.h" @@ -742,13 +743,10 @@ int process_load(process_t *process, vm_object_t *o, off_t base, size_t size, vo Elf32_Ehdr *ehdr; Elf32_Phdr *phdr; Elf32_Shdr *shdr, *shstrshdr; -#ifdef __sparc__ - Elf32_Rela *rela; - Elf32_Sym *sym; - ptr_t symTab; -#else - Elf32_Rel *rel; -#endif + Elf32_Rela rela; + int isrela; + Elf32_Addr symval; + Elf32_Sym *symTab = NULL; unsigned prot, flags, reloffs; int i, j, relocsz = 0, reltype, badreloc = 0, err; void *relptr; @@ -877,93 +875,76 @@ int process_load(process_t *process, vm_object_t *o, off_t base, size_t size, vo return -ENOEXEC; } -#ifdef __sparc__ /* find symtab */ for (i = 0, shdr = (void *)((char *)ehdr + ehdr->e_shoff); i < ehdr->e_shnum; i++, shdr++) { if (hal_strcmp(&snameTab[shdr->sh_name], ".symtab") == 0) { + symTab = (void *)((ptr_t)ehdr + (ptr_t)shdr->sh_offset); break; } } - if (i >= ehdr->e_shnum) { - return -ENOEXEC; - } - symTab = (ptr_t)ehdr + (ptr_t)shdr->sh_offset; - /* Perform data, init_array and fini_array relocation */ for (i = 0, shdr = (void *)((char *)ehdr + ehdr->e_shoff); i < ehdr->e_shnum; i++, shdr++) { - /* strncmp as there may be multiple .rela.* sections for different sections. */ - if (hal_strncmp(&snameTab[shdr->sh_name], ".rela", 5) != 0) { - continue; - } - if ((shdr->sh_size == 0) || (shdr->sh_entsize == 0)) { continue; } - for (j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j) { - rela = (Elf32_Rela *)((ptr_t)shdr->sh_offset + (ptr_t)ehdr + (j * shdr->sh_entsize)); - reltype = ELF32_R_TYPE(rela->r_info); - - if (reltype == R_SPARC_32) { - relptr = (void *)rela->r_offset; - if (process_relocate(reloc, relocsz, (char **)&relptr) < 0) { - return -ENOEXEC; - } - - /* Don't modify ELF file! */ - if (((ptr_t)relptr >= (ptr_t)base) && ((ptr_t)relptr < ((ptr_t)base + size))) { - ++badreloc; - continue; - } - - sym = (Elf32_Sym *)(symTab + (ELF32_R_SYM(rela->r_info) * sizeof(Elf32_Sym))); - - /* Write addend to the address */ - *(char **)relptr = (char *)(sym->st_value + rela->r_addend); - - if (process_relocate(reloc, relocsz, relptr) < 0) { - return -ENOEXEC; - } - } + /* strncmp as there may be multiple .rela.* or .rel.* sections for different sections. */ + if (hal_strncmp(&snameTab[shdr->sh_name], ".rela.", 6) == 0) { + isrela = 1; } - } -#else - /* Perform data, init_array and fini_array relocation */ - for (i = 0, shdr = (void *)((char *)ehdr + ehdr->e_shoff); i < ehdr->e_shnum; i++, shdr++) { - /* strncmp as there may be multiple .rel.* sections for different sections. */ - if (hal_strncmp(&snameTab[shdr->sh_name], ".rel", 4) != 0) { - continue; + else if (hal_strncmp(&snameTab[shdr->sh_name], ".rel.", 5) == 0) { + isrela = 0; } - - if ((shdr->sh_size == 0) || (shdr->sh_entsize == 0)) { + else { continue; } - for (j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j) { - rel = (void *)((ptr_t)shdr->sh_offset + (ptr_t)ehdr + (j * shdr->sh_entsize)); - reltype = ELF32_R_TYPE(rel->r_info); + for (j = 0; j < (shdr->sh_size / shdr->sh_entsize); ++j) { + /* Valid for both Elf32_Rela and Elf32_Rel, due to correct size being stored in shdr->sh_entsize. */ + /* For .rel. section make sure not to access addend field! */ + hal_memcpy(&rela, (Elf32_Rela *)((ptr_t)shdr->sh_offset + (ptr_t)ehdr + (j * shdr->sh_entsize)), shdr->sh_entsize); + reltype = ELF32_R_TYPE(rela.r_info); - if (reltype == R_ARM_ABS32 || reltype == R_ARM_TARGET1) { - relptr = (void *)rel->r_offset; + if (hal_isRelReloc(reltype) == 0) { + continue; + } - if (process_relocate(reloc, relocsz, (char **)&relptr) < 0) { - return -ENOEXEC; - } + relptr = (void *)rela.r_offset; + if (process_relocate(reloc, relocsz, (char **)&relptr) < 0) { + return -ENOEXEC; + } - /* Don't modify ELF file! */ - if (((ptr_t)relptr >= (ptr_t)base) && ((ptr_t)relptr < ((ptr_t)base + size))) { - ++badreloc; - continue; - } + /* Don't modify ELF file! */ + if (((ptr_t)relptr >= (ptr_t)base) && ((ptr_t)relptr < ((ptr_t)base + size))) { + ++badreloc; + continue; + } - if (process_relocate(reloc, relocsz, relptr) < 0) { + if (symTab == NULL) { + /* Accept files stripped from symtab if only SYM_UND is present, eg. files stripped with strip.py */ + if (ELF32_R_SYM(rela.r_info) != 0) { return -ENOEXEC; } + symval = 0; + } + else { + symval = symTab[ELF32_R_SYM(rela.r_info)].st_value; + } + + if (isrela == 0) { + /* If Rel is used addend stored is in the location. */ + *(char **)relptr += symval; + } + else { + *(char **)relptr = (char *)(symval + rela.r_addend); + } + + if (process_relocate(reloc, relocsz, relptr) < 0) { + return -ENOEXEC; } } } -#endif tlsNew.tls_base = NULL; tlsNew.tdata_sz = 0;