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;
 }