diff --git a/arch/xtensa/include/elf.h b/arch/xtensa/include/elf.h new file mode 100644 index 0000000000000..c46144b2020fe --- /dev/null +++ b/arch/xtensa/include/elf.h @@ -0,0 +1,35 @@ +/**************************************************************************** + * arch/xtensa/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_XTENSA_INCLUDE_ELF_H +#define __ARCH_XTENSA_INCLUDE_ELF_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Relocation codes */ + +#define R_XTENSA_NONE 0 +#define R_XTENSA_32 1 +#define R_XTENSA_ASM_EXPAND 11 +#define R_XTENSA_SLOT0_OP 20 + +#endif /* __ARCH_XTENSA_INCLUDE_ELF_H */ diff --git a/boards/xtensa/esp32/esp32-core/scripts/Make.defs b/boards/xtensa/esp32/esp32-core/scripts/Make.defs index 1f6682c11c757..c230ad630bed9 100644 --- a/boards/xtensa/esp32/esp32-core/scripts/Make.defs +++ b/boards/xtensa/esp32/esp32-core/scripts/Make.defs @@ -102,6 +102,29 @@ 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) -mtext-section-literals + +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) -mtext-section-literals +CXXELFFLAGS = $(CXXFLAGS) -mtext-section-literals + +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 + ASMEXT = .S OBJEXT = .o LIBEXT = .a diff --git a/boards/xtensa/esp32/esp32-core/scripts/gnu-elf.ld b/boards/xtensa/esp32/esp32-core/scripts/gnu-elf.ld new file mode 100644 index 0000000000000..e867083abba1f --- /dev/null +++ b/boards/xtensa/esp32/esp32-core/scripts/gnu-elf.ld @@ -0,0 +1,115 @@ +/**************************************************************************** + * boards/xtensa/esp32/esp32-core/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 */ + _ectors = . ; + } + + .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/elf.h b/include/elf.h index d048b69a161b0..47038c0a09241 100644 --- a/include/elf.h +++ b/include/elf.h @@ -71,6 +71,7 @@ #define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ #define EM_V850 87 /* NEC v850 */ #define EM_M32R 88 /* Renesas M32R */ +#define EM_XTENSA 94 /* Tensilca Xtensa */ #define EM_RISCV 243 /* RISC-V */ #define EM_ALPHA 0x9026 #define EM_CYGNUS_V850 0x9080 diff --git a/libs/libc/machine/Make.defs b/libs/libc/machine/Make.defs index efe95aa56e1da..8cfd702964922 100644 --- a/libs/libc/machine/Make.defs +++ b/libs/libc/machine/Make.defs @@ -45,3 +45,6 @@ endif ifeq ($(CONFIG_ARCH_X86),y) include ${TOPDIR}/libs/libc/machine/x86/Make.defs endif +ifeq ($(CONFIG_ARCH_XTENSA),y) +include ${TOPDIR}/libs/libc/machine/xtensa/Make.defs +endif diff --git a/libs/libc/machine/xtensa/Kconfig b/libs/libc/machine/xtensa/Kconfig new file mode 100644 index 0000000000000..f72f3c094ce4c --- /dev/null +++ b/libs/libc/machine/xtensa/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/xtensa/Make.defs b/libs/libc/machine/xtensa/Make.defs new file mode 100644 index 0000000000000..8f33a82488dfc --- /dev/null +++ b/libs/libc/machine/xtensa/Make.defs @@ -0,0 +1,28 @@ +############################################################################ +# libs/libc/machine/xtensa/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/xtensa +VPATH += :machine/xtensa + +endif diff --git a/libs/libc/machine/xtensa/arch_elf.c b/libs/libc/machine/xtensa/arch_elf.c new file mode 100644 index 0000000000000..830df7da94439 --- /dev/null +++ b/libs/libc/machine/xtensa/arch_elf.c @@ -0,0 +1,217 @@ +/**************************************************************************** + * libs/libc/machine/xtensa/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 + +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static bool is_l32r(const unsigned char *p) +{ + return (p[0] & 0xf) == 1; +} + +/**************************************************************************** + * 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 Elf32_Ehdr *ehdr) +{ + /* Make sure it's an Xtensa executable */ + + if (ehdr->e_machine != EM_XTENSA) + { + berr("ERROR: Not for ARM: e_machine=%04x\n", ehdr->e_machine); + return false; + } + + /* Make sure that 32-bit objects are supported */ + + if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) + { + berr("ERROR: Need 32-bit objects: e_ident[EI_CLASS]=%02x\n", ehdr->e_ident[EI_CLASS]); + return false; + } + + /* Verify endian-ness */ + +#ifdef CONFIG_ENDIAN_BIG +#error not implemented + 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; + } + + 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 Elf32_Rel *rel, FAR const Elf32_Sym *sym, + uintptr_t addr) +{ + unsigned int relotype; + + /* All relocations except R_ARM_V4BX depend upon having valid symbol + * information. + */ + + relotype = ELF32_R_TYPE(rel->r_info); + if (sym == NULL && relotype != R_XTENSA_NONE) + { + return -EINVAL; + } + + /* Handle the relocation by relocation type */ + + switch (relotype) + { + case R_XTENSA_NONE: + { + /* No relocation */ + } + break; + + default: + berr("ERROR: Unsupported relocation: %u\n", relotype); + return -EINVAL; + } + + return OK; +} + +int up_relocateadd(FAR const Elf32_Rela *rel, FAR const Elf32_Sym *sym, + uintptr_t addr) +{ + unsigned int relotype; + unsigned char *p; + uint32_t value; + + relotype = ELF32_R_TYPE(rel->r_info); + value = sym->st_value + rel->r_addend; + + /* Handle the relocation by relocation type */ + + switch (relotype) + { + case R_XTENSA_32: + (*(uint32_t *)addr) += value; + break; + + case R_XTENSA_ASM_EXPAND: + bwarn("ERROR: Ignoring RELA relocation R_XTENSA_ASM_EXPAND %u\n", + relotype); + break; + + case R_XTENSA_SLOT0_OP: + p = (unsigned char *)addr; + if (is_l32r(p)) + { + /* Xtensa ISA: + * L32R forms a virtual address by adding the 16-bit one-extended + * constant value encoded in the instruction word shifted left by + * two to the address of the L32R plus three with the two least + * significant bits cleared. + */ + + uintptr_t base = (addr + 3) & ~3; + uint16_t imm = (value - base) >> 2; + if (base + (0xfffc0000 | ((uint32_t)imm << 2)) != value) + { + berr("ERROR: Out of range rellocation at %p\n", p); + return -EINVAL; + } + + p[1] = imm & 0xff; + p[2] = (imm >> 8) & 0xff; + break; + } + + bwarn("ERROR: Ignoring RELA relocation R_XTENSA_SLOT0_OP %u\n", relotype); + break; + + default: + berr("ERROR: RELA relocation %u not supported\n", relotype); + return -EINVAL; + } + + return OK; +} diff --git a/tools/nxstyle.c b/tools/nxstyle.c index bdd5bd0cc55dc..077afd8ceb03f 100644 --- a/tools/nxstyle.c +++ b/tools/nxstyle.c @@ -699,7 +699,7 @@ int main(int argc, char **argv, char **envp) * preceding line has no comment. */ - if (line[n] != '}' /* && line[n] != '#' */ && !prevbrhcmt) + if (line[n] != '}' && line[n] != '#' && !prevbrhcmt) { ERROR("Missing blank line after comment", comment_lineno, 1);