You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/03/16 13:55:10 UTC
[incubator-nuttx] 08/14: xtensa: Implement a few relocations
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
commit e135c938d2466f21225966d04b337922bbfa9da8
Author: YAMAMOTO Takashi <ya...@midokura.com>
AuthorDate: Thu Mar 5 19:11:32 2020 +0900
xtensa: Implement a few relocations
---
arch/xtensa/include/elf.h | 5 ++-
libs/libc/machine/xtensa/arch_elf.c | 65 +++++++++++++++++++++++++++++++++++--
2 files changed, 66 insertions(+), 4 deletions(-)
diff --git a/arch/xtensa/include/elf.h b/arch/xtensa/include/elf.h
index 829b717..c46144b 100644
--- a/arch/xtensa/include/elf.h
+++ b/arch/xtensa/include/elf.h
@@ -27,6 +27,9 @@
/* Relocation codes */
-#define R_XTENSA_NONE 0
+#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/libs/libc/machine/xtensa/arch_elf.c b/libs/libc/machine/xtensa/arch_elf.c
index 9d567fb..84a8848 100644
--- a/libs/libc/machine/xtensa/arch_elf.c
+++ b/libs/libc/machine/xtensa/arch_elf.c
@@ -24,6 +24,7 @@
#include <nuttx/config.h>
+#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <debug.h>
@@ -43,6 +44,11 @@
* Private Functions
****************************************************************************/
+static bool is_l32r(FAR const unsigned char *p)
+{
+ return (p[0] & 0xf) == 1;
+}
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -85,6 +91,7 @@ bool up_checkarch(FAR const Elf32_Ehdr *ehdr)
/* 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)
@@ -146,7 +153,7 @@ int up_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym,
break;
default:
- berr("ERROR: Unsupported relocation: %d\n", ELF32_R_TYPE(rel->r_info));
+ berr("ERROR: Unsupported relocation: %u\n", relotype);
return -EINVAL;
}
@@ -156,6 +163,58 @@ int up_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym,
int up_relocateadd(FAR const Elf32_Rela *rel, FAR const Elf32_Sym *sym,
uintptr_t addr)
{
- berr("ERROR: RELA relocation not supported\n");
- return -ENOSYS;
+ 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:
+ (*(FAR uint32_t *)addr) += value;
+ break;
+
+ case R_XTENSA_ASM_EXPAND:
+ bwarn("WARNING: Ignoring RELA relocation R_XTENSA_ASM_EXPAND %u\n",
+ relotype);
+ break;
+
+ case R_XTENSA_SLOT0_OP:
+ p = (FAR 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("WARNING: 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;
}