This is an automated email from the ASF dual-hosted git repository. gnutt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push: new 81f1133 ELF64 support (#220) 81f1133 is described below commit 81f1133174f586b86829925a49686d9709b1dea4 Author: Masayuki Ishikawa <masayuki.ishik...@gmail.com> AuthorDate: Fri Feb 7 17:10:23 2020 -0600 ELF64 support (#220) * include: Introduce elf64.h and elf.h Added elf64.h for 64bit ELF support and moved common definitions from elf32.h to elf.h. Also introduced Elf_xxx to be used in common libraries such as binfmt. * binfmt, include, modlib, module: Add support for ELF64 Elf_xxx must be used instead of Elf32_xxx to support ELF64. To use ELF64, CONFIG_ELF_64BIT must be enabled. * binfmt, modlib: Add support for relocate address * arch: risc-v: Add include/elf.h * libs: machine: Add risc-v related files. NOTE: Currently only supports ELF64 * boards: maix-bit: Add elf and posix_spawn configurations * boards: maix-bit: Add support for module configuration --- arch/risc-v/include/elf.h | 86 ++++ binfmt/elf.c | 2 +- binfmt/libelf/Kconfig | 6 + binfmt/libelf/libelf.h | 6 +- binfmt/libelf/libelf_bind.c | 275 +++++++++++-- binfmt/libelf/libelf_ctors.c | 2 +- binfmt/libelf/libelf_dtors.c | 2 +- binfmt/libelf/libelf_init.c | 4 +- binfmt/libelf/libelf_load.c | 7 +- binfmt/libelf/libelf_sections.c | 8 +- binfmt/libelf/libelf_symbols.c | 19 +- binfmt/libelf/libelf_verify.c | 2 +- boards/risc-v/k210/maix-bit/configs/elf/defconfig | 59 +++ .../risc-v/k210/maix-bit/configs/module/defconfig | 61 +++ .../k210/maix-bit/configs/posix_spawn/defconfig | 57 +++ boards/risc-v/k210/maix-bit/scripts/Make.defs | 27 ++ boards/risc-v/k210/maix-bit/scripts/gnu-elf.ld | 115 ++++++ include/{elf32.h => elf.h} | 206 ++-------- include/elf32.h | 193 +-------- include/elf64.h | 157 ++++++++ include/nuttx/binfmt/elf.h | 12 +- include/nuttx/elf.h | 12 +- include/nuttx/lib/modlib.h | 11 +- libs/libc/dlfcn/lib_dlopen.c | 2 +- libs/libc/machine/Kconfig | 3 + libs/libc/machine/Make.defs | 3 + libs/libc/machine/risc-v/Kconfig | 9 + libs/libc/machine/risc-v/Make.defs | 23 ++ libs/libc/machine/risc-v/rv64/Kconfig | 4 + libs/libc/machine/risc-v/rv64/Make.defs | 28 ++ libs/libc/machine/risc-v/rv64/arch_elf.c | 432 +++++++++++++++++++++ libs/libc/modlib/modlib.h | 6 +- libs/libc/modlib/modlib_bind.c | 254 ++++++++++-- libs/libc/modlib/modlib_init.c | 4 +- libs/libc/modlib/modlib_load.c | 4 +- libs/libc/modlib/modlib_sections.c | 8 +- libs/libc/modlib/modlib_symbols.c | 16 +- libs/libc/modlib/modlib_verify.c | 2 +- libs/libxx/libxx__gnu_unwind_find_exidx.cxx | 2 +- sched/module/mod_insmod.c | 2 +- 40 files changed, 1663 insertions(+), 468 deletions(-) diff --git a/arch/risc-v/include/elf.h b/arch/risc-v/include/elf.h new file mode 100644 index 0000000..6fd222b --- /dev/null +++ b/arch/risc-v/include/elf.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * arch/risc-v/include/elf.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_INCLUDE_ELF_H +#define __ARCH_RISCV_INCLUDE_ELF_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md */ + +#define R_RISCV_NONE 0 +#define R_RISCV_32 1 +#define R_RISCV_64 2 +#define R_RISCV_RELATIVE 3 +#define R_RISCV_COPY 4 +#define R_RISCV_JUMP_SLOT 5 +#define R_RISCV_TLS_DTPMOD32 6 +#define R_RISCV_TLS_DTPMOD64 7 +#define R_RISCV_TLS_DTPREL32 8 +#define R_RISCV_TLS_DTPREL64 9 +#define R_RISCV_TLS_TPREL32 10 +#define R_RISCV_TLS_TPREL64 11 + +#define R_RISCV_BRANCH 16 +#define R_RISCV_JAL 17 +#define R_RISCV_CALL 18 +#define R_RISCV_CALL_PLT 19 +#define R_RISCV_GOT_HI20 20 +#define R_RISCV_TLS_GOT_HI20 21 +#define R_RISCV_TLS_GD_HI20 22 +#define R_RISCV_PCREL_HI20 23 +#define R_RISCV_PCREL_LO12_I 24 +#define R_RISCV_PCREL_LO12_S 25 +#define R_RISCV_HI20 26 +#define R_RISCV_LO12_I 27 +#define R_RISCV_LO12_S 28 +#define R_RISCV_TPREL_HI20 29 +#define R_RISCV_TPREL_LO12_I 30 +#define R_RISCV_TPREL_LO12_S 31 +#define R_RISCV_TPREL_ADD 32 +#define R_RISCV_ADD8 33 +#define R_RISCV_ADD16 34 +#define R_RISCV_ADD32 35 +#define R_RISCV_ADD64 36 +#define R_RISCV_SUB8 37 +#define R_RISCV_SUB16 38 +#define R_RISCV_SUB32 39 +#define R_RISCV_SUB64 40 +#define R_RISCV_GNU_VTINHERIT 41 +#define R_RISCV_GNU_VTENTRY 42 +#define R_RISCV_ALIGN 43 +#define R_RISCV_RVC_BRANCH 44 +#define R_RISCV_RVC_JUMP 45 +#define R_RISCV_RVC_LUI 46 +#define R_RISCV_GPREL_I 47 +#define R_RISCV_GPREL_S 48 +#define R_RISCV_TPREL_I 49 +#define R_RISCV_TPREL_S 50 +#define R_RISCV_RELAX 51 +#define R_RISCV_SUB6 52 +#define R_RISCV_SET6 53 +#define R_RISCV_SET8 54 +#define R_RISCV_SET16 55 +#define R_RISCV_SET32 56 +#define R_RISCV_32_PCREL 57 + +#endif /* __ARCH_RISCV_INCLUDE_ELF_H */ diff --git a/binfmt/elf.c b/binfmt/elf.c index 7177d27..66632d7 100644 --- a/binfmt/elf.c +++ b/binfmt/elf.c @@ -152,7 +152,7 @@ static void elf_dumploadinfo(FAR struct elf_loadinfo_s *loadinfo) { for (i = 0; i < loadinfo->ehdr.e_shnum; i++) { - FAR Elf32_Shdr *shdr = &loadinfo->shdr[i]; + FAR Elf_Shdr *shdr = &loadinfo->shdr[i]; binfo("Sections %d:\n", i); binfo(" sh_name: %08x\n", shdr->sh_name); binfo(" sh_type: %08x\n", shdr->sh_type); diff --git a/binfmt/libelf/Kconfig b/binfmt/libelf/Kconfig index 5f2f292..1546d2b 100644 --- a/binfmt/libelf/Kconfig +++ b/binfmt/libelf/Kconfig @@ -3,6 +3,12 @@ # see the file kconfig-language.txt in the NuttX tools repository. # +config ELF_64BIT + bool "64bit ELF support" + default n + ---help--- + This option is used to load 64bit ELF files + config ELF_ALIGN_LOG2 int "Log2 Section Alignment" default 2 diff --git a/binfmt/libelf/libelf.h b/binfmt/libelf/libelf.h index 350b3c5..0c2b712 100644 --- a/binfmt/libelf/libelf.h +++ b/binfmt/libelf/libelf.h @@ -64,7 +64,7 @@ * ****************************************************************************/ -int elf_verifyheader(FAR const Elf32_Ehdr *header); +int elf_verifyheader(FAR const Elf_Ehdr *header); /**************************************************************************** * Name: elf_read @@ -150,7 +150,7 @@ int elf_findsymtab(FAR struct elf_loadinfo_s *loadinfo); ****************************************************************************/ int elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index, - FAR Elf32_Sym *sym); + FAR Elf_Sym *sym); /**************************************************************************** * Name: elf_symvalue @@ -177,7 +177,7 @@ int elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index, * ****************************************************************************/ -int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf32_Sym *sym, +int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf_Sym *sym, FAR const struct symtab_s *exports, int nexports); /**************************************************************************** diff --git a/binfmt/libelf/libelf_bind.c b/binfmt/libelf/libelf_bind.c index 1fb1ab5..6eb500a 100644 --- a/binfmt/libelf/libelf_bind.c +++ b/binfmt/libelf/libelf_bind.c @@ -74,14 +74,14 @@ * Private Types ****************************************************************************/ -struct elf32_symcache_s +struct elf_symcache_s { dq_entry_t entry; - Elf32_Sym sym; + Elf_Sym sym; int idx; }; -typedef struct elf32_symcache_s elf32_symcache_t; +typedef struct elf_symcache_s elf_symcache_t; /**************************************************************************** * Private Data @@ -95,13 +95,13 @@ typedef struct elf32_symcache_s elf32_symcache_t; * Name: elf_readrels * * Description: - * Read the (ELF32_Rel structure * buffer count) into memory. + * Read the (ELF_Rel structure * buffer count) into memory. * ****************************************************************************/ static inline int elf_readrels(FAR struct elf_loadinfo_s *loadinfo, - FAR const Elf32_Shdr *relsec, - int index, FAR Elf32_Rel *rels, + FAR const Elf_Shdr *relsec, + int index, FAR Elf_Rel *rels, int count) { off_t offset; @@ -109,7 +109,7 @@ static inline int elf_readrels(FAR struct elf_loadinfo_s *loadinfo, /* Verify that the symbol table index lies within symbol table */ - if (index < 0 || index > (relsec->sh_size / sizeof(Elf32_Rel))) + if (index < 0 || index > (relsec->sh_size / sizeof(Elf_Rel))) { berr("Bad relocation symbol index: %d\n", index); return -EINVAL; @@ -117,8 +117,9 @@ static inline int elf_readrels(FAR struct elf_loadinfo_s *loadinfo, /* Get the file offset to the symbol table entry */ - offset = sizeof(Elf32_Rel) * index; - size = sizeof(Elf32_Rel) * count; + offset = sizeof(Elf_Rel) * index; + size = sizeof(Elf_Rel) * count; + if (offset + size > relsec->sh_size) { size = relsec->sh_size - offset; @@ -131,6 +132,46 @@ static inline int elf_readrels(FAR struct elf_loadinfo_s *loadinfo, } /**************************************************************************** + * Name: elf_readrelas + * + * Description: + * Read the (ELF_Rela structure * buffer count) into memory. + * + ****************************************************************************/ + +static inline int elf_readrelas(FAR struct elf_loadinfo_s *loadinfo, + FAR const Elf_Shdr *relsec, + int index, FAR Elf_Rela *relas, + int count) +{ + off_t offset; + int size; + + /* Verify that the symbol table index lies within symbol table */ + + if (index < 0 || index > (relsec->sh_size / sizeof(Elf_Rela))) + { + berr("Bad relocation symbol index: %d\n", index); + return -EINVAL; + } + + /* Get the file offset to the symbol table entry */ + + offset = sizeof(Elf_Rela) * index; + size = sizeof(Elf_Rela) * count; + + if (offset + size > relsec->sh_size) + { + size = relsec->sh_size - offset; + } + + /* And, finally, read the symbol table entry into memory */ + + return elf_read(loadinfo, (FAR uint8_t *)relas, size, + relsec->sh_offset + offset); +} + +/**************************************************************************** * Name: elf_relocate and elf_relocateadd * * Description: @@ -144,14 +185,13 @@ static inline int elf_readrels(FAR struct elf_loadinfo_s *loadinfo, static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx, FAR const struct symtab_s *exports, int nexports) - { - FAR Elf32_Shdr *relsec = &loadinfo->shdr[relidx]; - FAR Elf32_Shdr *dstsec = &loadinfo->shdr[relsec->sh_info]; - FAR Elf32_Rel *rels; - FAR Elf32_Rel *rel; - FAR elf32_symcache_t *cache; - FAR Elf32_Sym *sym; + FAR Elf_Shdr *relsec = &loadinfo->shdr[relidx]; + FAR Elf_Shdr *dstsec = &loadinfo->shdr[relsec->sh_info]; + FAR Elf_Rel *rels; + FAR Elf_Rel *rel; + FAR elf_symcache_t *cache; + FAR Elf_Sym *sym; FAR dq_entry_t *e; dq_queue_t q; uintptr_t addr; @@ -160,7 +200,7 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx, int i; int j; - rels = kmm_malloc(CONFIG_ELF_RELOCATION_BUFFERCOUNT * sizeof(Elf32_Rel)); + rels = kmm_malloc(CONFIG_ELF_RELOCATION_BUFFERCOUNT * sizeof(Elf_Rel)); if (rels == NULL) { berr("Failed to allocate memory for elf relocation\n"); @@ -176,7 +216,7 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx, ret = OK; - for (i = j = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++) + for (i = j = 0; i < relsec->sh_size / sizeof(Elf_Rel); i++) { /* Read the relocation entry into memory */ @@ -198,14 +238,14 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx, * in a bit-field within the r_info element. */ - symidx = ELF32_R_SYM(rel->r_info); + symidx = ELF_R_SYM(rel->r_info); /* First try the cache */ sym = NULL; for (e = dq_peek(&q); e; e = dq_next(e)) { - cache = (FAR elf32_symcache_t *)e; + cache = (FAR elf_symcache_t *)e; if (cache->idx == symidx) { dq_rem(&cache->entry, &q); @@ -223,7 +263,7 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx, { if (j < CONFIG_ELF_SYMBOL_CACHECOUNT) { - cache = kmm_malloc(sizeof(elf32_symcache_t)); + cache = kmm_malloc(sizeof(elf_symcache_t)); if (!cache) { berr("Failed to allocate memory for elf symbols\n"); @@ -235,7 +275,7 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx, } else { - cache = (FAR elf32_symcache_t *)dq_remlast(&q); + cache = (FAR elf_symcache_t *)dq_remlast(&q); } sym = &cache->sym; @@ -268,12 +308,14 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx, if (ret == -ESRCH) { - berr("Section %d reloc %d: Undefined symbol[%d] has no name: %d\n", - relidx, i, symidx, ret); + berr("Section %d reloc %d: " + "Undefined symbol[%d] has no name: %d\n", + relidx, i, symidx, ret); } else { - berr("Section %d reloc %d: Failed to get value of symbol[%d]: %d\n", + berr("Section %d reloc %d: " + "Failed to get value of symbol[%d]: %d\n", relidx, i, symidx, ret); kmm_free(cache); break; @@ -308,7 +350,8 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx, ret = up_relocate(rel, sym, addr); if (ret < 0) { - berr("ERROR: Section %d reloc %d: Relocation failed: %d\n", relidx, i, ret); + berr("ERROR: Section %d reloc %d: Relocation failed: %d\n", + relidx, i, ret); break; } } @@ -326,8 +369,184 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx, static int elf_relocateadd(FAR struct elf_loadinfo_s *loadinfo, int relidx, FAR const struct symtab_s *exports, int nexports) { - berr("Not implemented\n"); - return -ENOSYS; + FAR Elf_Shdr *relsec = &loadinfo->shdr[relidx]; + FAR Elf_Shdr *dstsec = &loadinfo->shdr[relsec->sh_info]; + FAR Elf_Rela *relas; + FAR Elf_Rela *rela; + FAR elf_symcache_t *cache; + FAR Elf_Sym *sym; + FAR dq_entry_t *e; + dq_queue_t q; + uintptr_t addr; + int symidx; + int ret; + int i; + int j; + + relas = kmm_malloc(CONFIG_ELF_RELOCATION_BUFFERCOUNT * sizeof(Elf_Rela)); + if (relas == NULL) + { + berr("Failed to allocate memory for elf relocation\n"); + return -ENOMEM; + } + + dq_init(&q); + + /* Examine each relocation in the section. 'relsec' is the section + * containing the relations. 'dstsec' is the section containing the data + * to be relocated. + */ + + ret = OK; + + for (i = j = 0; i < relsec->sh_size / sizeof(Elf_Rela); i++) + { + /* Read the relocation entry into memory */ + + rela = &relas[i % CONFIG_ELF_RELOCATION_BUFFERCOUNT]; + + if (!(i % CONFIG_ELF_RELOCATION_BUFFERCOUNT)) + { + ret = elf_readrelas(loadinfo, relsec, i, relas, + CONFIG_ELF_RELOCATION_BUFFERCOUNT); + if (ret < 0) + { + berr("Section %d reloc %d: Failed to read relocation entry: %d\n", + relidx, i, ret); + break; + } + } + + /* Get the symbol table index for the relocation. This is contained + * in a bit-field within the r_info element. + */ + + symidx = ELF_R_SYM(rela->r_info); + + /* First try the cache */ + + sym = NULL; + for (e = dq_peek(&q); e; e = dq_next(e)) + { + cache = (FAR elf_symcache_t *)e; + if (cache->idx == symidx) + { + dq_rem(&cache->entry, &q); + dq_addfirst(&cache->entry, &q); + sym = &cache->sym; + break; + } + } + + /* If the symbol was not found in the cache, we will need to read the + * symbol from the file. + */ + + if (sym == NULL) + { + if (j < CONFIG_ELF_SYMBOL_CACHECOUNT) + { + cache = kmm_malloc(sizeof(elf_symcache_t)); + if (!cache) + { + berr("Failed to allocate memory for elf symbols\n"); + ret = -ENOMEM; + break; + } + + j++; + } + else + { + cache = (FAR elf_symcache_t *)dq_remlast(&q); + } + + sym = &cache->sym; + + /* Read the symbol table entry into memory */ + + ret = elf_readsym(loadinfo, symidx, sym); + if (ret < 0) + { + berr("Section %d reloc %d: Failed to read symbol[%d]: %d\n", + relidx, i, symidx, ret); + kmm_free(cache); + break; + } + + /* Get the value of the symbol (in sym.st_value) */ + + ret = elf_symvalue(loadinfo, sym, exports, nexports); + if (ret < 0) + { + /* The special error -ESRCH is returned only in one condition: The + * symbol has no name. + * + * There are a few relocations for a few architectures that do + * no depend upon a named symbol. We don't know if that is the + * case here, but we will use a NULL symbol pointer to indicate + * that case to up_relocate(). That function can then do what + * is best. + */ + + if (ret == -ESRCH) + { + berr("Section %d reloc %d: " + "Undefined symbol[%d] has no name: %d\n", + relidx, i, symidx, ret); + } + else + { + berr("Section %d reloc %d: " + "Failed to get value of symbol[%d]: %d\n", + relidx, i, symidx, ret); + kmm_free(cache); + break; + } + } + + cache->idx = symidx; + dq_addfirst(&cache->entry, &q); + } + + if (sym->st_shndx == SHN_UNDEF && sym->st_name == 0) + { + sym = NULL; + } + + /* Calculate the relocation address. */ + + if (rela->r_offset < 0 || + rela->r_offset > dstsec->sh_size) + { + berr("Section %d reloc %d: Relocation address out of range, " + "offset %d size %d\n", + relidx, i, rela->r_offset, dstsec->sh_size); + ret = -EINVAL; + break; + } + + addr = dstsec->sh_addr + rela->r_offset; + + /* Now perform the architecture-specific relocation */ + + ret = up_relocateadd(rela, sym, addr); + if (ret < 0) + { + berr("ERROR: Section %d reloc %d: Relocation failed: %d\n", + relidx, i, ret); + break; + } + } + + kmm_free(relas); + while ((e = dq_peek(&q))) + { + dq_rem(e, &q); + kmm_free(e); + } + + return ret; } /**************************************************************************** diff --git a/binfmt/libelf/libelf_ctors.c b/binfmt/libelf/libelf_ctors.c index 6994602..3715e3c 100644 --- a/binfmt/libelf/libelf_ctors.c +++ b/binfmt/libelf/libelf_ctors.c @@ -88,7 +88,7 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo) { - FAR Elf32_Shdr *shdr; + FAR Elf_Shdr *shdr; size_t ctorsize; int ctoridx; int ret; diff --git a/binfmt/libelf/libelf_dtors.c b/binfmt/libelf/libelf_dtors.c index 3bfa00e..62cb343 100644 --- a/binfmt/libelf/libelf_dtors.c +++ b/binfmt/libelf/libelf_dtors.c @@ -88,7 +88,7 @@ int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo) { - FAR Elf32_Shdr *shdr; + FAR Elf_Shdr *shdr; size_t dtorsize; int dtoridx; int ret; diff --git a/binfmt/libelf/libelf_init.c b/binfmt/libelf/libelf_init.c index 287aa81..99fa46b 100644 --- a/binfmt/libelf/libelf_init.c +++ b/binfmt/libelf/libelf_init.c @@ -173,7 +173,7 @@ int elf_init(FAR const char *filename, FAR struct elf_loadinfo_s *loadinfo) /* Read the ELF ehdr from offset 0 */ ret = elf_read(loadinfo, (FAR uint8_t *)&loadinfo->ehdr, - sizeof(Elf32_Ehdr), 0); + sizeof(Elf_Ehdr), 0); if (ret < 0) { berr("Failed to read ELF header: %d\n", ret); @@ -182,7 +182,7 @@ int elf_init(FAR const char *filename, FAR struct elf_loadinfo_s *loadinfo) } elf_dumpbuffer("ELF header", (FAR const uint8_t *)&loadinfo->ehdr, - sizeof(Elf32_Ehdr)); + sizeof(Elf_Ehdr)); /* Verify the ELF header */ diff --git a/binfmt/libelf/libelf_load.c b/binfmt/libelf/libelf_load.c index 3deff9d..e3bff22 100644 --- a/binfmt/libelf/libelf_load.c +++ b/binfmt/libelf/libelf_load.c @@ -106,7 +106,7 @@ static void elf_elfsize(struct elf_loadinfo_s *loadinfo) for (i = 0; i < loadinfo->ehdr.e_shnum; i++) { - FAR Elf32_Shdr *shdr = &loadinfo->shdr[i]; + FAR Elf_Shdr *shdr = &loadinfo->shdr[i]; /* SHF_ALLOC indicates that the section requires memory during * execution. @@ -164,7 +164,7 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo) for (i = 0; i < loadinfo->ehdr.e_shnum; i++) { - FAR Elf32_Shdr *shdr = &loadinfo->shdr[i]; + FAR Elf_Shdr *shdr = &loadinfo->shdr[i]; /* SHF_ALLOC indicates that the section requires memory during * execution. @@ -286,7 +286,8 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo) /* Allocate (and zero) memory for the ELF file. */ - ret = elf_addrenv_alloc(loadinfo, loadinfo->textsize, loadinfo->datasize, heapsize); + ret = elf_addrenv_alloc(loadinfo, loadinfo->textsize, loadinfo->datasize, + heapsize); if (ret < 0) { berr("ERROR: elf_addrenv_alloc() failed: %d\n", ret); diff --git a/binfmt/libelf/libelf_sections.c b/binfmt/libelf/libelf_sections.c index 6f58b4a..8dd4930 100644 --- a/binfmt/libelf/libelf_sections.c +++ b/binfmt/libelf/libelf_sections.c @@ -75,9 +75,9 @@ ****************************************************************************/ static inline int elf_sectname(FAR struct elf_loadinfo_s *loadinfo, - FAR const Elf32_Shdr *shdr) + FAR const Elf_Shdr *shdr) { - FAR Elf32_Shdr *shstr; + FAR Elf_Shdr *shstr; FAR uint8_t *buffer; off_t offset; size_t readlen; @@ -210,7 +210,7 @@ int elf_loadshdrs(FAR struct elf_loadinfo_s *loadinfo) /* Allocate memory to hold a working copy of the sector header table */ - loadinfo->shdr = (FAR FAR Elf32_Shdr *)kmm_malloc(shdrsize); + loadinfo->shdr = (FAR FAR Elf_Shdr *)kmm_malloc(shdrsize); if (!loadinfo->shdr) { berr("Failed to allocate the section header table. Size: %ld\n", @@ -249,7 +249,7 @@ int elf_loadshdrs(FAR struct elf_loadinfo_s *loadinfo) int elf_findsection(FAR struct elf_loadinfo_s *loadinfo, FAR const char *sectname) { - FAR const Elf32_Shdr *shdr; + FAR const Elf_Shdr *shdr; int ret; int i; diff --git a/binfmt/libelf/libelf_symbols.c b/binfmt/libelf/libelf_symbols.c index cc435af..695fefa 100644 --- a/binfmt/libelf/libelf_symbols.c +++ b/binfmt/libelf/libelf_symbols.c @@ -78,7 +78,7 @@ ****************************************************************************/ static int elf_symname(FAR struct elf_loadinfo_s *loadinfo, - FAR const Elf32_Sym *sym) + FAR const Elf_Sym *sym) { FAR uint8_t *buffer; off_t offset; @@ -215,14 +215,14 @@ int elf_findsymtab(FAR struct elf_loadinfo_s *loadinfo) ****************************************************************************/ int elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index, - FAR Elf32_Sym *sym) + FAR Elf_Sym *sym) { - FAR Elf32_Shdr *symtab = &loadinfo->shdr[loadinfo->symtabidx]; + FAR Elf_Shdr *symtab = &loadinfo->shdr[loadinfo->symtabidx]; off_t offset; /* Verify that the symbol table index lies within symbol table */ - if (index < 0 || index > (symtab->sh_size / sizeof(Elf32_Sym))) + if (index < 0 || index > (symtab->sh_size / sizeof(Elf_Sym))) { berr("Bad relocation symbol index: %d\n", index); return -EINVAL; @@ -230,11 +230,11 @@ int elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index, /* Get the file offset to the symbol table entry */ - offset = symtab->sh_offset + sizeof(Elf32_Sym) * index; + offset = symtab->sh_offset + sizeof(Elf_Sym) * index; /* And, finally, read the symbol table entry into memory */ - return elf_read(loadinfo, (FAR uint8_t *)sym, sizeof(Elf32_Sym), offset); + return elf_read(loadinfo, (FAR uint8_t *)sym, sizeof(Elf_Sym), offset); } /**************************************************************************** @@ -260,7 +260,7 @@ int elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index, * ****************************************************************************/ -int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf32_Sym *sym, +int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf_Sym *sym, FAR const struct symtab_s *exports, int nexports) { FAR const struct symtab_s *symbol; @@ -314,7 +314,8 @@ int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf32_Sym *sym, #endif if (!symbol) { - berr("SHN_UNDEF: Exported symbol \"%s\" not found\n", loadinfo->iobuffer); + berr("SHN_UNDEF: Exported symbol \"%s\" not found\n", + loadinfo->iobuffer); return -ENOENT; } @@ -324,7 +325,7 @@ int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf32_Sym *sym, loadinfo->iobuffer, sym->st_value, symbol->sym_value, sym->st_value + symbol->sym_value); - sym->st_value += (Elf32_Word)((uintptr_t)symbol->sym_value); + sym->st_value += (Elf_Word)((uintptr_t)symbol->sym_value); } break; diff --git a/binfmt/libelf/libelf_verify.c b/binfmt/libelf/libelf_verify.c index d06b6f8..186d212 100644 --- a/binfmt/libelf/libelf_verify.c +++ b/binfmt/libelf/libelf_verify.c @@ -84,7 +84,7 @@ static const char g_elfmagic[EI_MAGIC_SIZE] = * ****************************************************************************/ -int elf_verifyheader(FAR const Elf32_Ehdr *ehdr) +int elf_verifyheader(FAR const Elf_Ehdr *ehdr) { if (!ehdr) { diff --git a/boards/risc-v/k210/maix-bit/configs/elf/defconfig b/boards/risc-v/k210/maix-bit/configs/elf/defconfig new file mode 100644 index 0000000..2a63aff --- /dev/null +++ b/boards/risc-v/k210/maix-bit/configs/elf/defconfig @@ -0,0 +1,59 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_STANDARD_SERIAL is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="maix-bit" +CONFIG_ARCH_BOARD_MAIX_BIT=y +CONFIG_ARCH_CHIP="k210" +CONFIG_ARCH_CHIP_K210=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_APP_SYMTAB=y +CONFIG_BOARD_LOOPSPERMSEC=46000 +CONFIG_BUILTIN=y +CONFIG_CXX_NEWLONG=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEV_ZERO=y +CONFIG_ELF=y +CONFIG_ELF_64BIT=y +CONFIG_ELF_ALIGN_LOG2=3 +CONFIG_EXAMPLES_ELF=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_HAVE_CXX=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_LIB_BOARDCTL=y +CONFIG_LIB_ENVPATH=y +CONFIG_MAX_TASKS=64 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_NFILE_STREAMS=8 +CONFIG_PATH_INITIAL="/mnt/romfs" +CONFIG_PIPES=y +CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=3072 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PREALLOC_WDOGS=16 +CONFIG_RAM_SIZE=2097152 +CONFIG_RAM_START=0x80400000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=5 +CONFIG_START_MONTH=2 +CONFIG_START_YEAR=2020 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_TASK_NAME_SIZE=20 +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_USERMAIN_STACKSIZE=3072 +CONFIG_USER_ENTRYPOINT="elf_main" +CONFIG_WDOG_INTRESERVE=0 diff --git a/boards/risc-v/k210/maix-bit/configs/module/defconfig b/boards/risc-v/k210/maix-bit/configs/module/defconfig new file mode 100644 index 0000000..1879ac0 --- /dev/null +++ b/boards/risc-v/k210/maix-bit/configs/module/defconfig @@ -0,0 +1,61 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_STANDARD_SERIAL is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="maix-bit" +CONFIG_ARCH_BOARD_MAIX_BIT=y +CONFIG_ARCH_CHIP="k210" +CONFIG_ARCH_CHIP_K210=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_APP_SYMTAB=y +CONFIG_BOARD_LOOPSPERMSEC=46000 +CONFIG_BUILTIN=y +CONFIG_CXX_NEWLONG=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEV_ZERO=y +CONFIG_ELF=y +CONFIG_ELF_64BIT=y +CONFIG_ELF_ALIGN_LOG2=3 +CONFIG_EXAMPLES_MODULE=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_HAVE_CXX=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_EXECFUNCS=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_LIB_BOARDCTL=y +CONFIG_LIB_ENVPATH=y +CONFIG_MAX_TASKS=64 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_MODULE=y +CONFIG_NFILE_STREAMS=8 +CONFIG_PATH_INITIAL="/mnt/romfs" +CONFIG_PIPES=y +CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=3072 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PREALLOC_WDOGS=16 +CONFIG_RAM_SIZE=2097152 +CONFIG_RAM_START=0x80400000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=5 +CONFIG_START_MONTH=2 +CONFIG_START_YEAR=2020 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_TASK_NAME_SIZE=20 +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_USERMAIN_STACKSIZE=3072 +CONFIG_USER_ENTRYPOINT="module_main" +CONFIG_WDOG_INTRESERVE=0 diff --git a/boards/risc-v/k210/maix-bit/configs/posix_spawn/defconfig b/boards/risc-v/k210/maix-bit/configs/posix_spawn/defconfig new file mode 100644 index 0000000..974b668 --- /dev/null +++ b/boards/risc-v/k210/maix-bit/configs/posix_spawn/defconfig @@ -0,0 +1,57 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_STANDARD_SERIAL is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="maix-bit" +CONFIG_ARCH_BOARD_MAIX_BIT=y +CONFIG_ARCH_CHIP="k210" +CONFIG_ARCH_CHIP_K210=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_APP_SYMTAB=y +CONFIG_BOARD_LOOPSPERMSEC=46000 +CONFIG_BUILTIN=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEV_ZERO=y +CONFIG_ELF=y +CONFIG_ELF_64BIT=y +CONFIG_EXAMPLES_POSIXSPAWN=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_EXECFUNCS=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_LIB_BOARDCTL=y +CONFIG_LIB_ENVPATH=y +CONFIG_MAX_TASKS=64 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_NFILE_STREAMS=8 +CONFIG_PATH_INITIAL="/mnt/romfs" +CONFIG_PIPES=y +CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=2048 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PREALLOC_WDOGS=16 +CONFIG_RAM_SIZE=2097152 +CONFIG_RAM_START=0x80400000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=28 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2019 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_TASK_NAME_SIZE=20 +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_USERMAIN_STACKSIZE=3072 +CONFIG_USER_ENTRYPOINT="posix_spawn_main" +CONFIG_WDOG_INTRESERVE=0 diff --git a/boards/risc-v/k210/maix-bit/scripts/Make.defs b/boards/risc-v/k210/maix-bit/scripts/Make.defs index 1ebda61..074a757 100644 --- a/boards/risc-v/k210/maix-bit/scripts/Make.defs +++ b/boards/risc-v/k210/maix-bit/scripts/Make.defs @@ -94,10 +94,37 @@ CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) AFLAGS += $(CFLAGS) -D__ASSEMBLY__ $(ASARCHCPUFLAGS) +# NXFLAT module definitions + NXFLATLDFLAGS1 = -r -d -warn-common NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections LDNXFLATFLAGS = -e main -s 2048 +# Loadable module definitions + +CMODULEFLAGS = $(CFLAGS) + +LDMODULEFLAGS = -r -e module_initialize +ifeq ($(WINTOOL),y) + LDMODULEFLAGS += -T "${shell cygpath -w $(TOPDIR)/libs/libc/modlib/gnu-elf.ld}" +else + LDMODULEFLAGS += -T $(TOPDIR)/libs/libc/modlib/gnu-elf.ld +endif + +# ELF module definitions + +CELFFLAGS = $(CFLAGS) +CXXELFFLAGS = $(CXXFLAGS) + +LDELFFLAGS = -r -e main +ifeq ($(WINTOOL),y) + LDELFFLAGS += -T "${shell cygpath -w $(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/gnu-elf.ld}" +else + LDELFFLAGS += -T $(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/gnu-elf.ld +endif + +# File extensions + ASMEXT = .S OBJEXT = .o LIBEXT = .a diff --git a/boards/risc-v/k210/maix-bit/scripts/gnu-elf.ld b/boards/risc-v/k210/maix-bit/scripts/gnu-elf.ld new file mode 100644 index 0000000..8e24692 --- /dev/null +++ b/boards/risc-v/k210/maix-bit/scripts/gnu-elf.ld @@ -0,0 +1,115 @@ +/**************************************************************************** + * boards/risc-v/k210/maix-bit/scripts/gnu-elf.ld + * + * 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. + * + ****************************************************************************/ + +SECTIONS +{ + .text 0x00000000 : + { + _stext = . ; + *(.text) + *(.text.*) + *(.gnu.warning) + *(.stub) + *(.glue_7) + *(.glue_7t) + *(.jcr) + + /* C++ support: The .init and .fini sections contain specific logic + * to manage static constructors and destructors. + */ + + *(.gnu.linkonce.t.*) + *(.init) /* Old ABI */ + *(.fini) /* Old ABI */ + _etext = . ; + } + + .rodata : + { + _srodata = . ; + *(.rodata) + *(.rodata1) + *(.rodata.*) + *(.gnu.linkonce.r*) + _erodata = . ; + } + + .data : + { + _sdata = . ; + *(.data) + *(.data1) + *(.data.*) + *(.gnu.linkonce.d*) + . = ALIGN(4); + _edata = . ; + } + + /* C++ support. For each global and static local C++ object, + * GCC creates a small subroutine to construct the object. Pointers + * to these routines (not the routines themselves) are stored as + * simple, linear arrays in the .ctors section of the object file. + * Similarly, pointers to global/static destructor routines are + * stored in .dtors. + */ + + .ctors : + { + _sctors = . ; + *(.ctors) /* Old ABI: Unallocated */ + *(.init_array) /* New ABI: Allocated */ + _edtors = . ; + } + + .dtors : + { + _sdtors = . ; + *(.dtors) /* Old ABI: Unallocated */ + *(.fini_array) /* New ABI: Allocated */ + _edtors = . ; + } + + .bss : + { + _sbss = . ; + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.b*) + *(COMMON) + _ebss = . ; + } + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/include/elf32.h b/include/elf.h similarity index 56% copy from include/elf32.h copy to include/elf.h index e16ae00..d048b69 100644 --- a/include/elf32.h +++ b/include/elf.h @@ -1,43 +1,25 @@ /**************************************************************************** - * include/elf32.h + * include/elf.h * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <gn...@nuttx.org> + * 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 * - * Reference: System V Application Binary Interface, Edition 4.1, March 18, - * 1997, The Santa Cruz Operation, Inc. + * http://www.apache.org/licenses/LICENSE-2.0 * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * 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. * ****************************************************************************/ -#ifndef __INCLUDE_ELF32_H -#define __INCLUDE_ELF32_H +#ifndef __INCLUDE_ELF_H +#define __INCLUDE_ELF_H /**************************************************************************** * Included Files @@ -51,11 +33,7 @@ * Pre-processor Definitions ****************************************************************************/ -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* Values for Elf32_Ehdr::e_type */ +/* Values for Elf_Ehdr::e_type */ #define ET_NONE 0 /* No file type */ #define ET_REL 1 /* Relocatable file */ @@ -65,7 +43,7 @@ #define ET_LOPROC 0xff00 /* Processor-specific */ #define ET_HIPROC 0xffff /* Processor-specific */ -/* Values for Elf32_Ehdr::e_machine (most of this were not included in the +/* Values for Elf_Ehdr::e_machine (most of this were not included in the * original SCO document but have been gleaned from elsewhere). */ @@ -86,60 +64,59 @@ #define EM_ARM 40 /* ARM */ #define EM_SH 42 /* SuperH */ #define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_H8_300 46 #define EM_IA_64 50 /* HP/Intel IA-64 */ #define EM_X86_64 62 /* AMD x86-64 */ #define EM_S390 22 /* IBM S/390 */ #define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ #define EM_V850 87 /* NEC v850 */ #define EM_M32R 88 /* Renesas M32R */ -#define EM_H8_300 46 +#define EM_RISCV 243 /* RISC-V */ #define EM_ALPHA 0x9026 #define EM_CYGNUS_V850 0x9080 #define EM_CYGNUS_M32R 0x9041 #define EM_S390_OLD 0xa390 #define EM_FRV 0x5441 -/* Values for Elf32_Ehdr::e_version */ +/* Values for Elf_Ehdr::e_version */ #define EV_NONE 0 /* Invalid version */ #define EV_CURRENT 1 /* The current version */ -/* Ehe ELF identifier */ +/* Table 2. Ehe ELF identifier */ #define EI_MAG0 0 /* File identification */ -#define EI_MAG1 1 /* " " " " */ -#define EI_MAG2 2 /* " " " " */ -#define EI_MAG3 3 /* " " " " */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 #define EI_CLASS 4 /* File class */ #define EI_DATA 5 /* Data encoding */ #define EI_VERSION 6 /* File version */ #define EI_PAD 7 /* Start of padding bytes */ -#define EI_NIDENT 16 /* Size of eident[] */ +#define EI_NIDENT 16 /* Size of e_ident[] */ #define EI_MAGIC_SIZE 4 #define EI_MAGIC {0x7f, 'E', 'L', 'F'} -/* Values for EI_CLASS */ +/* Table 3. Values for EI_CLASS */ #define ELFCLASSNONE 0 /* Invalid class */ #define ELFCLASS32 1 /* 32-bit objects */ #define ELFCLASS64 2 /* 64-bit objects */ -/* Values for EI_DATA */ +/* Table 4. Values for EI_DATA */ #define ELFDATANONE 0 /* Invalid data encoding */ #define ELFDATA2LSB 1 /* Least significant byte occupying the lowest address */ #define ELFDATA2MSB 2 /* Most significant byte occupying the lowest address */ -/* Figure 4-7: Special Section Indexes */ +/* Table 7: Special Section Indexes */ #define SHN_UNDEF 0 -#define SHN_LORESERVE 0xff00 #define SHN_LOPROC 0xff00 #define SHN_HIPROC 0xff1f #define SHN_ABS 0xfff1 #define SHN_COMMON 0xfff2 -#define SHN_HIRESERVE 0xffff /* Figure 4-9: Section Types, sh_type */ @@ -167,13 +144,7 @@ #define SHF_EXECINSTR 4 #define SHF_MASKPROC 0xf0000000 -/* Definitions for Elf32_Sym::st_info */ - -#define ELF32_ST_BIND(i) ((i) >> 4) -#define ELF32_ST_TYPE(i) ((i) & 0xf) -#define ELF32_ST_INFO(b,t) (((b) << 4) | ((t) & 0xf)) - -/* Figure 4-16: Symbol Binding, ELF32_ST_BIND */ +/* Figure 4-16: Symbol Binding, ELF_ST_BIND */ #define STB_LOCAL 0 #define STB_GLOBAL 1 @@ -181,7 +152,7 @@ #define STB_LOPROC 13 #define STB_HIPROC 15 -/* Figure 4-17: Symbol Types, ELF32_ST_TYPE */ +/* Figure 4-17: Symbol Types, ELF_ST_TYPE */ #define STT_NOTYPE 0 #define STT_OBJECT 1 @@ -191,12 +162,6 @@ #define STT_LOPROC 13 #define STT_HIPROC 15 -/* Definitions for Elf32_Rel*::r_info */ - -#define ELF32_R_SYM(i) ((i) >> 8) -#define ELF32_R_TYPE(i) ((i) & 0xff) -#define ELF32_R_INFO(s,t) (((s)<< 8) | ((t) & 0xff)) - /* Figure 5-2: Segment Types, p_type */ #define PT_NULL 0 @@ -246,107 +211,12 @@ #define DT_LOPROC 0x70000000 /* d_un=unspecified */ #define DT_HIPROC 0x7fffffff /* d_un= unspecified */ -/**************************************************************************** - * Public Type Definitions - ****************************************************************************/ +/* NOTE: elf64.h and elf32.h refer EI_NIDENT defined above */ + +#ifdef CONFIG_ELF_64BIT +# include <elf64.h> +#else +# include <elf32.h> +#endif -/* Figure 4.2: 32-Bit Data Types */ - -typedef uint32_t Elf32_Addr; /* Unsigned program address */ -typedef uint16_t Elf32_Half; /* Unsigned medium integer */ -typedef uint32_t Elf32_Off; /* Unsigned file offset */ -typedef int32_t Elf32_Sword; /* Signed large integer */ -typedef uint32_t Elf32_Word; /* Unsigned large integer */ - -/* Figure 4-3: ELF Header */ - -typedef struct -{ - unsigned char e_ident[EI_NIDENT]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -} Elf32_Ehdr; - -/* Figure 4-8: Section Header */ - -typedef struct -{ - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -} Elf32_Shdr; - -/* Figure 4-15: Symbol Table Entry */ - -typedef struct -{ - Elf32_Word st_name; - Elf32_Addr st_value; - Elf32_Word st_size; - unsigned char st_info; - unsigned char st_other; - Elf32_Half st_shndx; -} Elf32_Sym; - -/* Figure 4-19: Relocation Entries */ - -typedef struct -{ - Elf32_Addr r_offset; - Elf32_Word r_info; -} Elf32_Rel; - -typedef struct -{ - Elf32_Addr r_offset; - Elf32_Word r_info; - Elf32_Sword r_addend; -} Elf32_Rela; - -/* Figure 5-1: Program Header */ - -typedef struct -{ - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; -} Elf32_Phdr; - -/* Figure 5-9: Dynamic Structure */ - -typedef struct -{ - Elf32_Sword d_tag; - union - { - Elf32_Word d_val; - Elf32_Addr d_ptr; - } d_un; -} Elf32_Dyn; - -//extern Elf32_Dyn _DYNAMIC[] ; - -#endif /* __INCLUDE_ELF32_H */ +#endif /* __INCLUDE_ELF_H */ diff --git a/include/elf32.h b/include/elf32.h index e16ae00..dad6450 100644 --- a/include/elf32.h +++ b/include/elf32.h @@ -46,205 +46,23 @@ #include <nuttx/config.h> #include <stdint.h> +#include <elf.h> /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* Values for Elf32_Ehdr::e_type */ - -#define ET_NONE 0 /* No file type */ -#define ET_REL 1 /* Relocatable file */ -#define ET_EXEC 2 /* Executable file */ -#define ET_DYN 3 /* Shared object file */ -#define ET_CORE 4 /* Core file */ -#define ET_LOPROC 0xff00 /* Processor-specific */ -#define ET_HIPROC 0xffff /* Processor-specific */ - -/* Values for Elf32_Ehdr::e_machine (most of this were not included in the - * original SCO document but have been gleaned from elsewhere). - */ - -#define EM_NONE 0 /* No machine */ -#define EM_M32 1 /* AT&T WE 32100 */ -#define EM_SPARC 2 /* SPARC */ -#define EM_386 3 /* Intel 80386 */ -#define EM_68K 4 /* Motorola 68000 */ -#define EM_88K 5 /* Motorola 88000 */ -#define EM_486 6 /* Intel 486+ */ -#define EM_860 7 /* Intel 80860 */ -#define EM_MIPS 8 /* MIPS R3000 Big-Endian */ -#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ -#define EM_PARISC 15 /* HPPA */ -#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ -#define EM_PPC 20 /* PowerPC */ -#define EM_PPC64 21 /* PowerPC64 */ -#define EM_ARM 40 /* ARM */ -#define EM_SH 42 /* SuperH */ -#define EM_SPARCV9 43 /* SPARC v9 64-bit */ -#define EM_IA_64 50 /* HP/Intel IA-64 */ -#define EM_X86_64 62 /* AMD x86-64 */ -#define EM_S390 22 /* IBM S/390 */ -#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ -#define EM_V850 87 /* NEC v850 */ -#define EM_M32R 88 /* Renesas M32R */ -#define EM_H8_300 46 -#define EM_ALPHA 0x9026 -#define EM_CYGNUS_V850 0x9080 -#define EM_CYGNUS_M32R 0x9041 -#define EM_S390_OLD 0xa390 -#define EM_FRV 0x5441 - -/* Values for Elf32_Ehdr::e_version */ - -#define EV_NONE 0 /* Invalid version */ -#define EV_CURRENT 1 /* The current version */ - -/* Ehe ELF identifier */ - -#define EI_MAG0 0 /* File identification */ -#define EI_MAG1 1 /* " " " " */ -#define EI_MAG2 2 /* " " " " */ -#define EI_MAG3 3 /* " " " " */ -#define EI_CLASS 4 /* File class */ -#define EI_DATA 5 /* Data encoding */ -#define EI_VERSION 6 /* File version */ -#define EI_PAD 7 /* Start of padding bytes */ -#define EI_NIDENT 16 /* Size of eident[] */ - -#define EI_MAGIC_SIZE 4 -#define EI_MAGIC {0x7f, 'E', 'L', 'F'} - -/* Values for EI_CLASS */ - -#define ELFCLASSNONE 0 /* Invalid class */ -#define ELFCLASS32 1 /* 32-bit objects */ -#define ELFCLASS64 2 /* 64-bit objects */ - -/* Values for EI_DATA */ - -#define ELFDATANONE 0 /* Invalid data encoding */ -#define ELFDATA2LSB 1 /* Least significant byte occupying the lowest address */ -#define ELFDATA2MSB 2 /* Most significant byte occupying the lowest address */ - -/* Figure 4-7: Special Section Indexes */ - -#define SHN_UNDEF 0 -#define SHN_LORESERVE 0xff00 -#define SHN_LOPROC 0xff00 -#define SHN_HIPROC 0xff1f -#define SHN_ABS 0xfff1 -#define SHN_COMMON 0xfff2 -#define SHN_HIRESERVE 0xffff - -/* Figure 4-9: Section Types, sh_type */ - -#define SHT_NULL 0 -#define SHT_PROGBITS 1 -#define SHT_SYMTAB 2 -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_HASH 5 -#define SHT_DYNAMIC 6 -#define SHT_NOTE 7 -#define SHT_NOBITS 8 -#define SHT_REL 9 -#define SHT_SHLIB 10 -#define SHT_DYNSYM 11 -#define SHT_LOPROC 0x70000000 -#define SHT_HIPROC 0x7fffffff -#define SHT_LOUSER 0x80000000 -#define SHT_HIUSER 0xffffffff - -/* Figure 4-11: Section Attribute Flags, sh_flags */ - -#define SHF_WRITE 1 -#define SHF_ALLOC 2 -#define SHF_EXECINSTR 4 -#define SHF_MASKPROC 0xf0000000 - -/* Definitions for Elf32_Sym::st_info */ - #define ELF32_ST_BIND(i) ((i) >> 4) #define ELF32_ST_TYPE(i) ((i) & 0xf) #define ELF32_ST_INFO(b,t) (((b) << 4) | ((t) & 0xf)) -/* Figure 4-16: Symbol Binding, ELF32_ST_BIND */ - -#define STB_LOCAL 0 -#define STB_GLOBAL 1 -#define STB_WEAK 2 -#define STB_LOPROC 13 -#define STB_HIPROC 15 - -/* Figure 4-17: Symbol Types, ELF32_ST_TYPE */ - -#define STT_NOTYPE 0 -#define STT_OBJECT 1 -#define STT_FUNC 2 -#define STT_SECTION 3 -#define STT_FILE 4 -#define STT_LOPROC 13 -#define STT_HIPROC 15 - /* Definitions for Elf32_Rel*::r_info */ #define ELF32_R_SYM(i) ((i) >> 8) #define ELF32_R_TYPE(i) ((i) & 0xff) #define ELF32_R_INFO(s,t) (((s)<< 8) | ((t) & 0xff)) -/* Figure 5-2: Segment Types, p_type */ - -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7fffffff - -/* Figure 5-3: Segment Flag Bits, p_flags */ - -#define PF_X 1 /* Execute */ -#define PF_W 2 /* Write */ -#define PF_R 4 /* Read */ -#define PF_MASKPROC 0xf0000000 /* Unspecified */ - -/* Figure 5-10: Dynamic Array Tags, d_tag */ - -#define DT_NULL 0 /* d_un=ignored */ -#define DT_NEEDED 1 /* d_un=d_val */ -#define DT_PLTRELSZ 2 /* d_un=d_val */ -#define DT_PLTGOT 3 /* d_un=d_ptr */ -#define DT_HASH 4 /* d_un=d_ptr */ -#define DT_STRTAB 5 /* d_un=d_ptr */ -#define DT_SYMTAB 6 /* d_un=d_ptr */ -#define DT_RELA 7 /* d_un=d_ptr */ -#define DT_RELASZ 8 /* d_un=d_val */ -#define DT_RELAENT 9 /* d_un=d_val */ -#define DT_STRSZ 10 /* d_un=d_val */ -#define DT_SYMENT 11 /* d_un=d_val */ -#define DT_INIT 12 /* d_un=d_ptr */ -#define DT_FINI 13 /* d_un=d_ptr */ -#define DT_SONAME 14 /* d_un=d_val */ -#define DT_RPATH 15 /* d_un=d_val */ -#define DT_SYMBOLIC 16 /* d_un=ignored */ -#define DT_REL 17 /* d_un=d_ptr */ -#define DT_RELSZ 18 /* d_un=d_val */ -#define DT_RELENT 19 /* d_un=d_val */ -#define DT_PLTREL 20 /* d_un=d_val */ -#define DT_DEBUG 21 /* d_un=d_ptr */ -#define DT_TEXTREL 22 /* d_un=ignored */ -#define DT_JMPREL 23 /* d_un=d_ptr */ -#define DT_BINDNOW 24 /* d_un=ignored */ -#define DT_LOPROC 0x70000000 /* d_un=unspecified */ -#define DT_HIPROC 0x7fffffff /* d_un= unspecified */ +#define ELF_R_SYM(i) ELF32_R_SYM(i) /**************************************************************************** * Public Type Definitions @@ -347,6 +165,11 @@ typedef struct } d_un; } Elf32_Dyn; -//extern Elf32_Dyn _DYNAMIC[] ; +typedef Elf32_Ehdr Elf_Ehdr; +typedef Elf32_Rel Elf_Rel; +typedef Elf32_Rela Elf_Rela; +typedef Elf32_Sym Elf_Sym; +typedef Elf32_Shdr Elf_Shdr; +typedef Elf32_Word Elf_Word; #endif /* __INCLUDE_ELF32_H */ diff --git a/include/elf64.h b/include/elf64.h new file mode 100644 index 0000000..dc86a61 --- /dev/null +++ b/include/elf64.h @@ -0,0 +1,157 @@ +/**************************************************************************** + * include/elf64.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __INCLUDE_ELF64_H +#define __INCLUDE_ELF64_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <elf.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* See ELF-64 Object File Format: Version 1.5 Draft 2 */ + +/* Definitions for Elf64_Rel*::r_info */ + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffffL) +#define ELF64_R_INFO(s,t) (((s)<< 32) + ((t) & 0xffffffffL)) + +#define ELF_R_SYM(i) ELF64_R_SYM(i) + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* Table 1: ELF-64 Data Types */ + +typedef uint64_t Elf64_Addr; /* Unsigned program address */ +typedef uint64_t Elf64_Off; /* Unsigned file offset */ +typedef uint16_t Elf64_Half; /* Unsigned medium integer */ +typedef uint32_t Elf64_Word; /* Unsigned long integer */ +typedef int32_t Elf64_Sword; /* Signed integer */ +typedef uint64_t Elf64_Xword; /* Unsigned long integer */ +typedef int64_t Elf64_Sxword; /* Signed large integer */ + +/* Figure 2: ELF-64 Header */ + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* ELF identification */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Machine type */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point address */ + Elf64_Off e_phoff; /* Program header offset */ + Elf64_Off e_shoff; /* Section header offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size */ + Elf64_Half e_phentsize; /* Size of program header entry */ + Elf64_Half e_phnum; /* Number of program header entry */ + Elf64_Half e_shentsize; /* Size of section header entry */ + Elf64_Half e_shnum; /* Number of section header entries */ + Elf64_Half e_shstrndx; /* Section name string table index */ +} Elf64_Ehdr; + +/* Figure 3: ELF-64 Section Header */ + +typedef struct +{ + Elf64_Word sh_name; /* Section name */ + Elf64_Word sh_type; /* Section type */ + Elf64_Xword sh_flags; /* Section attributes */ + Elf64_Addr sh_addr; /* Virtual address in memory */ + Elf64_Off sh_offset; /* Offset in file */ + Elf64_Xword sh_size; /* Size of section */ + Elf64_Word sh_link; /* Link to other section */ + Elf64_Word sh_info; /* Miscellaneous information */ + Elf64_Xword sh_addralign; /* Address alignment boundary */ + Elf64_Xword sh_entsize; /* Size of entries, if section has table */ +} Elf64_Shdr; + +/* Figure 4: ELF-64 Symbol Table Entry */ + +typedef struct +{ + Elf64_Word st_name; /* Symbol name */ + unsigned char st_info; /* Type and Binding attributes */ + unsigned char st_other; /* Reserved */ + Elf64_Half st_shndx; /* Section table index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Size of object (e.g., common) */ +} Elf64_Sym; + +/* Figure 5: ELF-64 Relocation Entries */ + +typedef struct +{ + Elf64_Addr r_offset; /* Address of reference */ + Elf64_Xword r_info; /* Symbol index and type of relocation */ +} Elf64_Rel; + +typedef struct +{ + Elf64_Addr r_offset; /* Address of reference */ + Elf64_Xword r_info; /* Symbol index and type of relocation */ + Elf64_Sxword r_addend; /* Constant part of expression */ +} Elf64_Rela; + +/* Figure 6: ELF-64 Program Header Table Entry */ + +typedef struct +{ + Elf64_Word p_type; /* Type of segment */ + Elf64_Word p_flags; /* Segment attributes */ + Elf64_Off p_offset; /* Offset in file */ + Elf64_Addr p_vaddr; /* Virtual address in memory */ + Elf64_Addr p_paddr; /* Reserved */ + Elf64_Word p_filesz; /* Size of segment in file */ + Elf64_Word p_memsz; /* Size of segment in memory */ + Elf64_Word p_align; /* Alignment of segment */ +} Elf64_Phdr; + +/* Figure 8: Dynamic Table Structure */ + +typedef struct +{ + Elf64_Sxword d_tag; + union + { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +typedef Elf64_Ehdr Elf_Ehdr; +typedef Elf64_Rel Elf_Rel; +typedef Elf64_Rela Elf_Rela; +typedef Elf64_Sym Elf_Sym; +typedef Elf64_Shdr Elf_Shdr; +typedef Elf64_Word Elf_Word; + +#endif /* __INCLUDE_ELF64_H */ diff --git a/include/nuttx/binfmt/elf.h b/include/nuttx/binfmt/elf.h index ea3cb08..5926008 100644 --- a/include/nuttx/binfmt/elf.h +++ b/include/nuttx/binfmt/elf.h @@ -1,7 +1,7 @@ /**************************************************************************** * include/nuttx/binfmt/elf.h * - * Copyright (C) 2012, 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2012, 2014, 2020 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gn...@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -46,7 +46,7 @@ #include <stdint.h> #include <stdbool.h> -#include <elf32.h> +#include <elf.h> #include <nuttx/arch.h> #include <nuttx/binfmt/binfmt.h> @@ -54,6 +54,7 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ + /* Configuration ************************************************************/ #ifndef CONFIG_ELF_ALIGN_LOG2 @@ -110,8 +111,9 @@ struct elf_loadinfo_s size_t textsize; /* Size of the ELF .text memory allocation */ size_t datasize; /* Size of the ELF .bss/.data memory allocation */ off_t filelen; /* Length of the entire ELF file */ - Elf32_Ehdr ehdr; /* Buffered ELF file header */ - FAR Elf32_Shdr *shdr; /* Buffered ELF section headers */ + + Elf_Ehdr ehdr; /* Buffered ELF file header */ + FAR Elf_Shdr *shdr; /* Buffered ELF section headers */ uint8_t *iobuffer; /* File I/O buffer */ /* Constructors and destructors */ @@ -145,7 +147,7 @@ struct elf_loadinfo_s }; /**************************************************************************** - * Public Functions + * Public Function Prototypes ****************************************************************************/ #undef EXTERN diff --git a/include/nuttx/elf.h b/include/nuttx/elf.h index ae90c74..0760f5b 100644 --- a/include/nuttx/elf.h +++ b/include/nuttx/elf.h @@ -40,7 +40,7 @@ * Included Files ****************************************************************************/ -#include <elf32.h> +#include <elf.h> /**************************************************************************** * Public Function Prototypes @@ -68,7 +68,7 @@ extern "C" ****************************************************************************/ #ifdef CONFIG_LIBC_ARCH_ELF -bool up_checkarch(FAR const Elf32_Ehdr *hdr); +bool up_checkarch(FAR const Elf_Ehdr *hdr); #endif /**************************************************************************** @@ -94,10 +94,10 @@ bool up_checkarch(FAR const Elf32_Ehdr *hdr); ****************************************************************************/ #ifdef CONFIG_LIBC_ARCH_ELF -int up_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym, +int up_relocate(FAR const Elf_Rel *rel, FAR const Elf_Sym *sym, uintptr_t addr); -int up_relocateadd(FAR const Elf32_Rela *rel, - FAR const Elf32_Sym *sym, uintptr_t addr); +int up_relocateadd(FAR const Elf_Rela *rel, + FAR const Elf_Sym *sym, uintptr_t addr); #endif /**************************************************************************** @@ -117,7 +117,7 @@ int up_relocateadd(FAR const Elf32_Rela *rel, ****************************************************************************/ #ifdef CONFIG_CXX_EXCEPTION -int up_init_exidx(Elf32_Addr address, Elf32_Word size); +int up_init_exidx(Elf_Addr address, Elf_Word size); #endif #if defined(__cplusplus) diff --git a/include/nuttx/lib/modlib.h b/include/nuttx/lib/modlib.h index e011d8e..6ba8049 100644 --- a/include/nuttx/lib/modlib.h +++ b/include/nuttx/lib/modlib.h @@ -1,7 +1,7 @@ /**************************************************************************** * include/nuttx/lib/modlib.h * - * Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2015, 2017, 2020 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gn...@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -43,7 +43,7 @@ #include <nuttx/config.h> #include <sys/types.h> -#include <elf32.h> +#include <elf.h> #include <nuttx/arch.h> #include <nuttx/symtab.h> @@ -51,6 +51,7 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ + /* Configuration ************************************************************/ #ifndef CONFIG_MODLIB_MAXDEPEND @@ -126,7 +127,7 @@ typedef CODE int (*mod_uninitializer_t)(FAR void *arg); * be returned if no uninitialization is needed (i.e, the * the module memory can be deallocated at any time). * arg - An argument that will be passed to the uninitialization - function. + * function. * exports - A symbol table exported by the module * nexports - The number of symbols in the exported symbol table. */ @@ -206,8 +207,8 @@ struct mod_loadinfo_s size_t textsize; /* Size of the module .text memory allocation */ size_t datasize; /* Size of the module .bss/.data memory allocation */ off_t filelen; /* Length of the entire module file */ - Elf32_Ehdr ehdr; /* Buffered module file header */ - FAR Elf32_Shdr *shdr; /* Buffered module section headers */ + Elf_Ehdr ehdr; /* Buffered module file header */ + FAR Elf_Shdr *shdr; /* Buffered module section headers */ uint8_t *iobuffer; /* File I/O buffer */ uint16_t symtabidx; /* Symbol table section index */ diff --git a/libs/libc/dlfcn/lib_dlopen.c b/libs/libc/dlfcn/lib_dlopen.c index dc98d17..d0e504f 100644 --- a/libs/libc/dlfcn/lib_dlopen.c +++ b/libs/libc/dlfcn/lib_dlopen.c @@ -98,7 +98,7 @@ static void dldump_loadinfo(FAR struct mod_loadinfo_s *loadinfo) { for (i = 0; i < loadinfo->ehdr.e_shnum; i++) { - FAR Elf32_Shdr *shdr = &loadinfo->shdr[i]; + FAR Elf_Shdr *shdr = &loadinfo->shdr[i]; binfo("Sections %d:\n", i); binfo(" sh_name: %08x\n", shdr->sh_name); binfo(" sh_type: %08x\n", shdr->sh_type); diff --git a/libs/libc/machine/Kconfig b/libs/libc/machine/Kconfig index 6584ff4..aea5619 100644 --- a/libs/libc/machine/Kconfig +++ b/libs/libc/machine/Kconfig @@ -153,6 +153,9 @@ config LIBM_ARCH_TRUNCF if ARCH_ARM source libs/libc/machine/arm/Kconfig endif +if ARCH_RISCV +source libs/libc/machine/risc-v/Kconfig +endif if ARCH_SIM source libs/libc/machine/sim/Kconfig endif diff --git a/libs/libc/machine/Make.defs b/libs/libc/machine/Make.defs index c362391..efe95aa 100644 --- a/libs/libc/machine/Make.defs +++ b/libs/libc/machine/Make.defs @@ -36,6 +36,9 @@ ifeq ($(CONFIG_ARCH_ARM),y) include ${TOPDIR}/libs/libc/machine/arm/Make.defs endif +ifeq ($(CONFIG_ARCH_RISCV),y) +include ${TOPDIR}/libs/libc/machine/risc-v/Make.defs +endif ifeq ($(CONFIG_ARCH_SIM),y) include ${TOPDIR}/libs/libc/machine/sim/Make.defs endif diff --git a/libs/libc/machine/risc-v/Kconfig b/libs/libc/machine/risc-v/Kconfig new file mode 100644 index 0000000..9478d84 --- /dev/null +++ b/libs/libc/machine/risc-v/Kconfig @@ -0,0 +1,9 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_RV64GC +source libs/libc/machine/risc-v/rv64/Kconfig +endif + diff --git a/libs/libc/machine/risc-v/Make.defs b/libs/libc/machine/risc-v/Make.defs new file mode 100644 index 0000000..b312789 --- /dev/null +++ b/libs/libc/machine/risc-v/Make.defs @@ -0,0 +1,23 @@ +############################################################################ +# libs/libc/machine/arm/Make.defs +# +# 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. +# +############################################################################ + +ifeq ($(CONFIG_ARCH_RV64GC),y) +include ${TOPDIR}/libs/libc/machine/risc-v/rv64/Make.defs +endif diff --git a/libs/libc/machine/risc-v/rv64/Kconfig b/libs/libc/machine/risc-v/rv64/Kconfig new file mode 100644 index 0000000..f72f3c0 --- /dev/null +++ b/libs/libc/machine/risc-v/rv64/Kconfig @@ -0,0 +1,4 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# diff --git a/libs/libc/machine/risc-v/rv64/Make.defs b/libs/libc/machine/risc-v/rv64/Make.defs new file mode 100644 index 0000000..a08bd9f --- /dev/null +++ b/libs/libc/machine/risc-v/rv64/Make.defs @@ -0,0 +1,28 @@ +############################################################################ +# libs/libc/machine/risc-v/rv64/Make.defs +# +# 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. +# +############################################################################ + +ifeq ($(CONFIG_LIBC_ARCH_ELF),y) + +CSRCS += arch_elf.c + +DEPPATH += --dep-path machine/risc-v/rv64 +VPATH += :machine/risc-v/rv64 + +endif diff --git a/libs/libc/machine/risc-v/rv64/arch_elf.c b/libs/libc/machine/risc-v/rv64/arch_elf.c new file mode 100644 index 0000000..259a22f --- /dev/null +++ b/libs/libc/machine/risc-v/rv64/arch_elf.c @@ -0,0 +1,432 @@ +/**************************************************************************** + * libs/libc/machine/risc-v/rv64/arch_elf.c + * + * 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 <stdlib.h> +#include <errno.h> +#include <debug.h> +#include <assert.h> + +#include <arch/elf.h> +#include <nuttx/elf.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define OPCODE_SW 0x23 + +/**************************************************************************** + * Private Data Types + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_BINFMT_INFO +struct rname_code_s +{ + const char *name; + int type; +}; +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_BINFMT_INFO +static struct rname_code_s _rname_table[] = +{ + {"RELAX", R_RISCV_RELAX}, + {"RISCV_64", R_RISCV_64}, + {"PCREL_LO12_I", R_RISCV_PCREL_LO12_I}, + {"PCREL_LO12_S", R_RISCV_PCREL_LO12_S}, + {"PCREL_HI20", R_RISCV_PCREL_HI20}, + {"CALL", R_RISCV_CALL}, + {"BRANCH", R_RISCV_BRANCH}, + {"RVC_JUMP", R_RISCV_RVC_JUMP}, + {"RVC_BRANCH", R_RISCV_RVC_BRANCH}, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_BINFMT_INFO +const char *_get_rname(int type) +{ + int i = 0; + + for (i = 0; i < sizeof(_rname_table) / sizeof(struct rname_code_s); i++) + { + if (_rname_table[i].type == type) + { + return _rname_table[i].name; + } + } + + /* Not found in the table */ + + return "?????"; +} +#endif + +/**************************************************************************** + * Name: _get_val, set_val, _add_val + * + * Description: + * These functions are used when relocating an instruction because we can + * not assume the instruction is word-aligned. + * + ****************************************************************************/ + +static uint32_t _get_val(uint16_t *addr) +{ + uint32_t ret; + ret = *addr | (*(addr + 1)) << 16; + return ret; +} + +static void _set_val(uint16_t *addr, uint32_t val) +{ + *addr = (val & 0xffff); + *(addr + 1) = (val >> 16); + + /* NOTE: Ensure relocation before execution */ + + asm volatile ("fence.i"); +} + +static void _add_val(uint16_t *addr, uint32_t val) +{ + uint32_t cur = _get_val(addr); + _set_val(addr, cur + val); +} + +/**************************************************************************** + * Name: _calc_imm + * + * Description: + * Given offset and obtain imm_hi (20bit) and imm_lo (12bit) + * + * Input Parameters: + * offset - signed 64bit + * imm_hi - signed 20bit + * imm_lo - signed 12bit + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void _calc_imm(long offset, long *imm_hi, long *imm_lo) +{ + long lo; + long hi = offset / 4096; + long r = offset % 4096; + + if (2047 < r) + { + hi++; + } + else if (r <= -2048) + { + hi--; + } + + lo = offset - (hi * 4096); + + binfo("offset=%ld: hi=%ld lo=%ld \n", + offset, hi, lo); + + ASSERT(-2048 <= lo && lo <= 2047); + + *imm_lo = lo; + *imm_hi = hi; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_checkarch + * + * Description: + * Given the ELF header in 'hdr', verify that the ELF file is appropriate + * for the current, configured architecture. Every architecture that uses + * the ELF loader must provide this function. + * + * Input Parameters: + * hdr - The ELF header read from the ELF file. + * + * Returned Value: + * True if the architecture supports this ELF file. + * + ****************************************************************************/ + +bool up_checkarch(FAR const Elf64_Ehdr *ehdr) +{ + /* Make sure it's an RISCV executable */ + + if (ehdr->e_machine != EM_RISCV) + { + berr("ERROR: Not for RISCV: e_machine=%04x\n", ehdr->e_machine); + return false; + } + + /* Make sure that 64-bit objects are supported */ + + if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) + { + berr("ERROR: Need 64-bit objects: e_ident[EI_CLASS]=%02x\n", + ehdr->e_ident[EI_CLASS]); + return false; + } + + /* Verify endian-ness */ + +#ifdef CONFIG_ENDIAN_BIG + if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) +#else + if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) +#endif + { + berr("ERROR: Wrong endian-ness: e_ident[EI_DATA]=%02x\n", + ehdr->e_ident[EI_DATA]); + return false; + } + + /* Make sure the entry point address is properly aligned */ + + if ((ehdr->e_entry & 1) != 0) + { + berr("ERROR: Entry point is not properly aligned: %08x\n", + ehdr->e_entry); + } + + /* TODO: Check ABI here. */ + + return true; +} + +/**************************************************************************** + * Name: up_relocate and up_relocateadd + * + * Description: + * Perform on architecture-specific ELF relocation. Every architecture + * that uses the ELF loader must provide this function. + * + * Input Parameters: + * rel - The relocation type + * sym - The ELF symbol structure containing the fully resolved value. + * There are a few relocation types for a few architectures that do + * not require symbol information. For those, this value will be + * NULL. Implementations of these functions must be able to handle + * that case. + * addr - The address that requires the relocation. + * + * Returned Value: + * Zero (OK) if the relocation was successful. Otherwise, a negated errno + * value indicating the cause of the relocation failure. + * + ****************************************************************************/ + +int up_relocate(FAR const Elf64_Rel *rel, FAR const Elf64_Sym *sym, + uintptr_t addr) +{ + berr("Not implemented\n"); + return -ENOSYS; +} + +int up_relocateadd(FAR const Elf64_Rela *rel, FAR const Elf64_Sym *sym, + uintptr_t addr) +{ + long offset; + unsigned int relotype; + + /* All relocations depend upon having valid symbol information */ + + relotype = ELF64_R_TYPE(rel->r_info); + + if (relotype == R_RISCV_RELAX) + { + /* NOTE: RELAX has no symbol, so just return */ + + binfo("%s at %08lx [%08x] \n", + _get_rname(relotype), + (long)addr, _get_val((uint16_t *)addr)); + + return OK; + } + + if (sym == NULL && relotype != R_RISCV_NONE) + { + return -EINVAL; + } + + /* Do relocation based on relocation type */ + + switch (relotype) + { + case R_RISCV_64: + { + binfo("%s at %08lx [%08x] to sym=%p st_value=%08lx\n", + _get_rname(relotype), + (long)addr, _get_val((uint16_t *)addr), + sym, (long)sym->st_value); + + _set_val((uint16_t *)addr, + (uint32_t)(sym->st_value + rel->r_addend)); + } + break; + + case R_RISCV_PCREL_LO12_I: + case R_RISCV_PCREL_LO12_S: + { + binfo("%s at %08lx [%08x] to sym=%p st_value=%08lx\n", + _get_rname(relotype), + (long)addr, _get_val((uint16_t *)addr), + sym, (long)sym->st_value); + + /* NOTE: imm value for mv has been adjusted in previous HI20 */ + } + break; + + case R_RISCV_PCREL_HI20: + case R_RISCV_CALL: + { + binfo("%s at %08lx [%08x] to sym=%p st_value=%08lx\n", + _get_rname(relotype), + (long)addr, _get_val((uint16_t *)addr), + sym, (long)sym->st_value); + + offset = (long)sym->st_value - (long)addr; + + long imm_hi; + long imm_lo; + + _calc_imm(offset, &imm_hi, &imm_lo); + + /* Adjust auipc (add upper immediate to pc) : 20bit */ + + _add_val((uint16_t *)addr, (imm_hi << 12)); + + if ((_get_val((uint16_t *)(addr + 4)) & 0x7f) == OPCODE_SW) + { + /* Adjust imm for SW : S-type */ + + uint32_t val = + (((int32_t)imm_lo >> 5) << 25) + + (((int32_t)imm_lo & 0x1f) << 7); + + binfo("imm_lo=%d (%x), val=%x \n", imm_lo, imm_lo, val); + + _add_val((uint16_t *)(addr + 4), val); + } + else + { + /* Adjust imm for MV(ADDI)/JALR : I-type */ + + _add_val((uint16_t *)(addr + 4), ((int32_t)imm_lo << 20)); + } + } + break; + + case R_RISCV_BRANCH: + { + binfo("%s at %08lx [%08x] to sym=%p st_value=%08lx\n", + _get_rname(relotype), + (long)addr, _get_val((uint16_t *)addr), + sym, (long)sym->st_value); + + /* P.23 Conditinal Branches : B type (imm=12bit) */ + + offset = (long)sym->st_value - (long)addr; + uint32_t val = _get_val((uint16_t *)addr) & 0xfe000f80; + + /* NOTE: we assume that a compiler adds an immediate value */ + + ASSERT(offset && val); + + binfo("offset for Bx=%ld (0x%x) (val=0x%08x) already set! \n", + offset, offset, val); + } + break; + + case R_RISCV_RVC_JUMP: + { + binfo("%s at %08lx [%04x] to sym=%p st_value=%08lx\n", + _get_rname(relotype), + (long)addr, _get_val((uint16_t *)addr), + sym, (long)sym->st_value); + + /* P.111 Table 16.6 : Instruction listings for RVC */ + + offset = ((long)sym->st_value - (long)addr); + ASSERT(-2048 <= offset && offset <= 2047); + + uint16_t val = (*(uint16_t *)addr) & 0x1ffc; + + /* NOTE: we assume that a compiler adds an immediate value */ + + ASSERT(offset && val); + + binfo("offset for C.J=%ld (0x%x) (val=0x%04x) already set! \n", + offset, offset, val); + } + break; + + case R_RISCV_RVC_BRANCH: + { + binfo("%s at %08lx [%04x] to sym=%p st_value=%08lx\n", + _get_rname(relotype), + (long)addr, _get_val((uint16_t *)addr), + sym, (long)sym->st_value); + + /* P.111 Table 16.6 : Instruction listings for RVC */ + + offset = ((long)sym->st_value - (long)addr); + ASSERT(-256 <= offset && offset <= 255); + + uint16_t val = (*(uint16_t *)addr) & 0x1c7c; + + /* NOTE: we assume that a compiler adds an immediate value */ + + ASSERT(offset && val); + + binfo("offset for C.Bx=%ld (0x%x) (val=0x%04x) already set!\n", + offset, offset, val); + } + break; + + default: + berr("ERROR: Unsupported relocation: %d\n", + ELF64_R_TYPE(rel->r_info)); + ASSERT(false); + return -EINVAL; + } + + return OK; +} diff --git a/libs/libc/modlib/modlib.h b/libs/libc/modlib/modlib.h index 1c4fb9a..26b1112 100644 --- a/libs/libc/modlib/modlib.h +++ b/libs/libc/modlib/modlib.h @@ -64,7 +64,7 @@ * ****************************************************************************/ -int modlib_verifyheader(FAR const Elf32_Ehdr *header); +int modlib_verifyheader(FAR const Elf_Ehdr *header); /**************************************************************************** * Name: modlib_findsymtab @@ -98,7 +98,7 @@ int modlib_findsymtab(FAR struct mod_loadinfo_s *loadinfo); ****************************************************************************/ int modlib_readsym(FAR struct mod_loadinfo_s *loadinfo, int index, - FAR Elf32_Sym *sym); + FAR Elf_Sym *sym); /**************************************************************************** * Name: modlib_symvalue @@ -125,7 +125,7 @@ int modlib_readsym(FAR struct mod_loadinfo_s *loadinfo, int index, ****************************************************************************/ int modlib_symvalue(FAR struct module_s *modp, - FAR struct mod_loadinfo_s *loadinfo, FAR Elf32_Sym *sym); + FAR struct mod_loadinfo_s *loadinfo, FAR Elf_Sym *sym); /**************************************************************************** * Name: modlib_loadshdrs diff --git a/libs/libc/modlib/modlib_bind.c b/libs/libc/modlib/modlib_bind.c index cb7af8d..866a502 100644 --- a/libs/libc/modlib/modlib_bind.c +++ b/libs/libc/modlib/modlib_bind.c @@ -56,15 +56,15 @@ ****************************************************************************/ /* REVISIT: This naming breaks the NuttX coding standard, but is consistent - * with legacy naming of other ELF32 types. + * with legacy naming of other ELF types. */ typedef struct { dq_entry_t entry; - Elf32_Sym sym; + Elf_Sym sym; int idx; -} Elf32_SymCache; +} Elf_SymCache; /**************************************************************************** * Private Functions @@ -74,13 +74,13 @@ typedef struct * Name: modlib_readrels * * Description: - * Read the (ELF32_Rel structure * buffer count) into memory. + * Read the (ELF_Rel structure * buffer count) into memory. * ****************************************************************************/ static inline int modlib_readrels(FAR struct mod_loadinfo_s *loadinfo, - FAR const Elf32_Shdr *relsec, - int index, FAR Elf32_Rel *rels, + FAR const Elf_Shdr *relsec, + int index, FAR Elf_Rel *rels, int count) { off_t offset; @@ -88,7 +88,7 @@ static inline int modlib_readrels(FAR struct mod_loadinfo_s *loadinfo, /* Verify that the symbol table index lies within symbol table */ - if (index < 0 || index > (relsec->sh_size / sizeof(Elf32_Rel))) + if (index < 0 || index > (relsec->sh_size / sizeof(Elf_Rel))) { berr("ERROR: Bad relocation symbol index: %d\n", index); return -EINVAL; @@ -96,8 +96,8 @@ static inline int modlib_readrels(FAR struct mod_loadinfo_s *loadinfo, /* Get the file offset to the symbol table entry */ - offset = sizeof(Elf32_Rel) * index; - size = sizeof(Elf32_Rel) * count; + offset = sizeof(Elf_Rel) * index; + size = sizeof(Elf_Rel) * count; if (offset + size > relsec->sh_size) { size = relsec->sh_size - offset; @@ -110,6 +110,45 @@ static inline int modlib_readrels(FAR struct mod_loadinfo_s *loadinfo, } /**************************************************************************** + * Name: modlib_readrelas + * + * Description: + * Read the (ELF_Rela structure * buffer count) into memory. + * + ****************************************************************************/ + +static inline int modlib_readrelas(FAR struct mod_loadinfo_s *loadinfo, + FAR const Elf_Shdr *relsec, + int index, FAR Elf_Rela *relas, + int count) +{ + off_t offset; + int size; + + /* Verify that the symbol table index lies within symbol table */ + + if (index < 0 || index > (relsec->sh_size / sizeof(Elf_Rela))) + { + berr("ERROR: Bad relocation symbol index: %d\n", index); + return -EINVAL; + } + + /* Get the file offset to the symbol table entry */ + + offset = sizeof(Elf_Rela) * index; + size = sizeof(Elf_Rela) * count; + if (offset + size > relsec->sh_size) + { + size = relsec->sh_size - offset; + } + + /* And, finally, read the symbol table entry into memory */ + + return modlib_read(loadinfo, (FAR uint8_t *)relas, size, + relsec->sh_offset + offset); +} + +/**************************************************************************** * Name: modlib_relocate and modlib_relocateadd * * Description: @@ -125,12 +164,12 @@ static int modlib_relocate(FAR struct module_s *modp, FAR struct mod_loadinfo_s *loadinfo, int relidx) { - FAR Elf32_Shdr *relsec = &loadinfo->shdr[relidx]; - FAR Elf32_Shdr *dstsec = &loadinfo->shdr[relsec->sh_info]; - FAR Elf32_Rel *rels; - FAR Elf32_Rel *rel; - FAR Elf32_SymCache *cache; - FAR Elf32_Sym *sym; + FAR Elf_Shdr *relsec = &loadinfo->shdr[relidx]; + FAR Elf_Shdr *dstsec = &loadinfo->shdr[relsec->sh_info]; + FAR Elf_Rel *rels; + FAR Elf_Rel *rel; + FAR Elf_SymCache *cache; + FAR Elf_Sym *sym; FAR dq_entry_t *e; dq_queue_t q; uintptr_t addr; @@ -139,7 +178,7 @@ static int modlib_relocate(FAR struct module_s *modp, int i; int j; - rels = lib_malloc(CONFIG_MODLIB_RELOCATION_BUFFERCOUNT * sizeof(Elf32_Rel)); + rels = lib_malloc(CONFIG_MODLIB_RELOCATION_BUFFERCOUNT * sizeof(Elf_Rel)); if (!rels) { berr("Failed to allocate memory for elf relocation rels\n"); @@ -155,7 +194,7 @@ static int modlib_relocate(FAR struct module_s *modp, ret = OK; - for (i = j = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++) + for (i = j = 0; i < relsec->sh_size / sizeof(Elf_Rel); i++) { /* Read the relocation entry into memory */ @@ -176,14 +215,14 @@ static int modlib_relocate(FAR struct module_s *modp, * in a bit-field within the r_info element. */ - symidx = ELF32_R_SYM(rel->r_info); + symidx = ELF_R_SYM(rel->r_info); /* First try the cache */ sym = NULL; for (e = dq_peek(&q); e; e = dq_next(e)) { - cache = (FAR Elf32_SymCache *)e; + cache = (FAR Elf_SymCache *)e; if (cache->idx == symidx) { dq_rem(&cache->entry, &q); @@ -201,7 +240,7 @@ static int modlib_relocate(FAR struct module_s *modp, { if (j < CONFIG_MODLIB_SYMBOL_CACHECOUNT) { - cache = lib_malloc(sizeof(Elf32_SymCache)); + cache = lib_malloc(sizeof(Elf_SymCache)); if (!cache) { berr("Failed to allocate memory for elf symbols\n"); @@ -212,7 +251,7 @@ static int modlib_relocate(FAR struct module_s *modp, } else { - cache = (FAR Elf32_SymCache *)dq_remlast(&q); + cache = (FAR Elf_SymCache *)dq_remlast(&q); } sym = &cache->sym; @@ -301,8 +340,177 @@ static int modlib_relocate(FAR struct module_s *modp, static int modlib_relocateadd(FAR struct module_s *modp, FAR struct mod_loadinfo_s *loadinfo, int relidx) { - berr("ERROR: Not implemented\n"); - return -ENOSYS; + FAR Elf_Shdr *relsec = &loadinfo->shdr[relidx]; + FAR Elf_Shdr *dstsec = &loadinfo->shdr[relsec->sh_info]; + FAR Elf_Rela *relas; + FAR Elf_Rela *rela; + FAR Elf_SymCache *cache; + FAR Elf_Sym *sym; + FAR dq_entry_t *e; + dq_queue_t q; + uintptr_t addr; + int symidx; + int ret; + int i; + int j; + + relas = lib_malloc(CONFIG_MODLIB_RELOCATION_BUFFERCOUNT * sizeof(Elf_Rela)); + if (!relas) + { + berr("Failed to allocate memory for elf relocation relas\n"); + return -ENOMEM; + } + + dq_init(&q); + + /* Examine each relocation in the section. 'relsec' is the section + * containing the relations. 'dstsec' is the section containing the data + * to be relocated. + */ + + ret = OK; + + for (i = j = 0; i < relsec->sh_size / sizeof(Elf_Rela); i++) + { + /* Read the relocation entry into memory */ + + rela = &relas[i % CONFIG_MODLIB_RELOCATION_BUFFERCOUNT]; + + if (!(i % CONFIG_MODLIB_RELOCATION_BUFFERCOUNT)) + { + ret = modlib_readrelas(loadinfo, relsec, i, relas, CONFIG_MODLIB_RELOCATION_BUFFERCOUNT); + if (ret < 0) + { + berr("ERROR: Section %d reloc %d: Failed to read relocation entry: %d\n", + relidx, i, ret); + break; + } + } + + /* Get the symbol table index for the relocation. This is contained + * in a bit-field within the r_info element. + */ + + symidx = ELF_R_SYM(rela->r_info); + + /* First try the cache */ + + sym = NULL; + for (e = dq_peek(&q); e; e = dq_next(e)) + { + cache = (FAR Elf_SymCache *)e; + if (cache->idx == symidx) + { + dq_rem(&cache->entry, &q); + dq_addfirst(&cache->entry, &q); + sym = &cache->sym; + break; + } + } + + /* If the symbol was not found in the cache, we will need to read the + * symbol from the file. + */ + + if (sym == NULL) + { + if (j < CONFIG_MODLIB_SYMBOL_CACHECOUNT) + { + cache = lib_malloc(sizeof(Elf_SymCache)); + if (!cache) + { + berr("Failed to allocate memory for elf symbols\n"); + ret = -ENOMEM; + break; + } + j++; + } + else + { + cache = (FAR Elf_SymCache *)dq_remlast(&q); + } + + sym = &cache->sym; + + /* Read the symbol table entry into memory */ + + ret = modlib_readsym(loadinfo, symidx, sym); + if (ret < 0) + { + berr("ERROR: Section %d reloc %d: Failed to read symbol[%d]: %d\n", + relidx, i, symidx, ret); + lib_free(cache); + break; + } + + /* Get the value of the symbol (in sym.st_value) */ + + ret = modlib_symvalue(modp, loadinfo, sym); + if (ret < 0) + { + /* The special error -ESRCH is returned only in one condition: The + * symbol has no name. + * + * There are a few relocations for a few architectures that do + * no depend upon a named symbol. We don't know if that is the + * case here, but we will use a NULL symbol pointer to indicate + * that case to up_relocate(). That function can then do what + * is best. + */ + + if (ret == -ESRCH) + { + berr("ERROR: Section %d reloc %d: Undefined symbol[%d] has no name: %d\n", + relidx, i, symidx, ret); + } + else + { + berr("ERROR: Section %d reloc %d: Failed to get value of symbol[%d]: %d\n", + relidx, i, symidx, ret); + lib_free(cache); + break; + } + } + + cache->idx = symidx; + dq_addfirst(&cache->entry, &q); + } + + if (sym->st_shndx == SHN_UNDEF && sym->st_name == 0) + { + sym = NULL; + } + + /* Calculate the relocation address. */ + + if (rela->r_offset < 0 || rela->r_offset > dstsec->sh_size - sizeof(uint32_t)) + { + berr("ERROR: Section %d reloc %d: Relocation address out of range, offset %d size %d\n", + relidx, i, rela->r_offset, dstsec->sh_size); + ret = -EINVAL; + break; + } + + addr = dstsec->sh_addr + rela->r_offset; + + /* Now perform the architecture-specific relocation */ + + ret = up_relocateadd(rela, sym, addr); + if (ret < 0) + { + berr("ERROR: Section %d reloc %d: Relocation failed: %d\n", relidx, i, ret); + break; + } + } + + lib_free(relas); + while ((e = dq_peek(&q))) + { + dq_rem(e, &q); + lib_free(e); + } + + return ret; } /**************************************************************************** diff --git a/libs/libc/modlib/modlib_init.c b/libs/libc/modlib/modlib_init.c index fdf8771..18d11c7 100644 --- a/libs/libc/modlib/modlib_init.c +++ b/libs/libc/modlib/modlib_init.c @@ -170,7 +170,7 @@ int modlib_initialize(FAR const char *filename, /* Read the ELF ehdr from offset 0 */ ret = modlib_read(loadinfo, (FAR uint8_t *)&loadinfo->ehdr, - sizeof(Elf32_Ehdr), 0); + sizeof(Elf_Ehdr), 0); if (ret < 0) { berr("ERROR: Failed to read ELF header: %d\n", ret); @@ -178,7 +178,7 @@ int modlib_initialize(FAR const char *filename, } modlib_dumpbuffer("ELF header", (FAR const uint8_t *)&loadinfo->ehdr, - sizeof(Elf32_Ehdr)); + sizeof(Elf_Ehdr)); /* Verify the ELF header */ diff --git a/libs/libc/modlib/modlib_load.c b/libs/libc/modlib/modlib_load.c index 24c7052..82daa22 100644 --- a/libs/libc/modlib/modlib_load.c +++ b/libs/libc/modlib/modlib_load.c @@ -99,7 +99,7 @@ static void modlib_elfsize(struct mod_loadinfo_s *loadinfo) for (i = 0; i < loadinfo->ehdr.e_shnum; i++) { - FAR Elf32_Shdr *shdr = &loadinfo->shdr[i]; + FAR Elf_Shdr *shdr = &loadinfo->shdr[i]; /* SHF_ALLOC indicates that the section requires memory during * execution. @@ -157,7 +157,7 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s *loadinfo) for (i = 0; i < loadinfo->ehdr.e_shnum; i++) { - FAR Elf32_Shdr *shdr = &loadinfo->shdr[i]; + FAR Elf_Shdr *shdr = &loadinfo->shdr[i]; /* SHF_ALLOC indicates that the section requires memory during * execution */ diff --git a/libs/libc/modlib/modlib_sections.c b/libs/libc/modlib/modlib_sections.c index 3b55882..fdb6218 100644 --- a/libs/libc/modlib/modlib_sections.c +++ b/libs/libc/modlib/modlib_sections.c @@ -67,9 +67,9 @@ ****************************************************************************/ static inline int modlib_sectname(FAR struct mod_loadinfo_s *loadinfo, - FAR const Elf32_Shdr *shdr) + FAR const Elf_Shdr *shdr) { - FAR Elf32_Shdr *shstr; + FAR Elf_Shdr *shstr; FAR uint8_t *buffer; off_t offset; size_t readlen; @@ -203,7 +203,7 @@ int modlib_loadshdrs(FAR struct mod_loadinfo_s *loadinfo) /* Allocate memory to hold a working copy of the sector header table */ - loadinfo->shdr = (FAR FAR Elf32_Shdr *)lib_malloc(shdrsize); + loadinfo->shdr = (FAR FAR Elf_Shdr *)lib_malloc(shdrsize); if (!loadinfo->shdr) { berr("ERROR: Failed to allocate the section header table. Size: %ld\n", @@ -243,7 +243,7 @@ int modlib_loadshdrs(FAR struct mod_loadinfo_s *loadinfo) int modlib_findsection(FAR struct mod_loadinfo_s *loadinfo, FAR const char *sectname) { - FAR const Elf32_Shdr *shdr; + FAR const Elf_Shdr *shdr; int ret; int i; diff --git a/libs/libc/modlib/modlib_symbols.c b/libs/libc/modlib/modlib_symbols.c index f14cba0..d320d96 100644 --- a/libs/libc/modlib/modlib_symbols.c +++ b/libs/libc/modlib/modlib_symbols.c @@ -89,7 +89,7 @@ struct mod_exportinfo_s ****************************************************************************/ static int modlib_symname(FAR struct mod_loadinfo_s *loadinfo, - FAR const Elf32_Sym *sym) + FAR const Elf_Sym *sym) { FAR uint8_t *buffer; off_t offset; @@ -276,14 +276,14 @@ int modlib_findsymtab(FAR struct mod_loadinfo_s *loadinfo) ****************************************************************************/ int modlib_readsym(FAR struct mod_loadinfo_s *loadinfo, int index, - FAR Elf32_Sym *sym) + FAR Elf_Sym *sym) { - FAR Elf32_Shdr *symtab = &loadinfo->shdr[loadinfo->symtabidx]; + FAR Elf_Shdr *symtab = &loadinfo->shdr[loadinfo->symtabidx]; off_t offset; /* Verify that the symbol table index lies within symbol table */ - if (index < 0 || index > (symtab->sh_size / sizeof(Elf32_Sym))) + if (index < 0 || index > (symtab->sh_size / sizeof(Elf_Sym))) { berr("ERROR: Bad relocation symbol index: %d\n", index); return -EINVAL; @@ -291,11 +291,11 @@ int modlib_readsym(FAR struct mod_loadinfo_s *loadinfo, int index, /* Get the file offset to the symbol table entry */ - offset = symtab->sh_offset + sizeof(Elf32_Sym) * index; + offset = symtab->sh_offset + sizeof(Elf_Sym) * index; /* And, finally, read the symbol table entry into memory */ - return modlib_read(loadinfo, (FAR uint8_t *)sym, sizeof(Elf32_Sym), offset); + return modlib_read(loadinfo, (FAR uint8_t *)sym, sizeof(Elf_Sym), offset); } /**************************************************************************** @@ -323,7 +323,7 @@ int modlib_readsym(FAR struct mod_loadinfo_s *loadinfo, int index, ****************************************************************************/ int modlib_symvalue(FAR struct module_s *modp, - FAR struct mod_loadinfo_s *loadinfo, FAR Elf32_Sym *sym) + FAR struct mod_loadinfo_s *loadinfo, FAR Elf_Sym *sym) { FAR const struct symtab_s *symbol; struct mod_exportinfo_s exportinfo; @@ -416,7 +416,7 @@ int modlib_symvalue(FAR struct module_s *modp, loadinfo->iobuffer, sym->st_value, symbol->sym_value, sym->st_value + symbol->sym_value); - sym->st_value += (Elf32_Word)((uintptr_t)symbol->sym_value); + sym->st_value += (Elf_Word)((uintptr_t)symbol->sym_value); } break; diff --git a/libs/libc/modlib/modlib_verify.c b/libs/libc/modlib/modlib_verify.c index 12040db..97bdf3d 100644 --- a/libs/libc/modlib/modlib_verify.c +++ b/libs/libc/modlib/modlib_verify.c @@ -77,7 +77,7 @@ static const char g_modmagic[EI_MAGIC_SIZE] = * ****************************************************************************/ -int modlib_verifyheader(FAR const Elf32_Ehdr *ehdr) +int modlib_verifyheader(FAR const Elf_Ehdr *ehdr) { if (!ehdr) { diff --git a/libs/libxx/libxx__gnu_unwind_find_exidx.cxx b/libs/libxx/libxx__gnu_unwind_find_exidx.cxx index 7f2ed19..08b67fa 100644 --- a/libs/libxx/libxx__gnu_unwind_find_exidx.cxx +++ b/libs/libxx/libxx__gnu_unwind_find_exidx.cxx @@ -85,7 +85,7 @@ extern "C" { - int up_init_exidx(Elf32_Addr start, Elf32_Word size) + int up_init_exidx(Elf_Addr start, Elf_Word size) { __exidx_start_elf = (__EIT_entry *) start; __exidx_end_elf = __exidx_start_elf + size; diff --git a/sched/module/mod_insmod.c b/sched/module/mod_insmod.c index 0cc2a8c..2209bef 100644 --- a/sched/module/mod_insmod.c +++ b/sched/module/mod_insmod.c @@ -106,7 +106,7 @@ static void mod_dumploadinfo(FAR struct mod_loadinfo_s *loadinfo) { for (i = 0; i < loadinfo->ehdr.e_shnum; i++) { - FAR Elf32_Shdr *shdr = &loadinfo->shdr[i]; + FAR Elf_Shdr *shdr = &loadinfo->shdr[i]; binfo("Sections %d:\n", i); binfo(" sh_name: %08x\n", shdr->sh_name); binfo(" sh_type: %08x\n", shdr->sh_type);