Handle ADD/SUB relocations
authorAndreas Schwab <schwab@suse.de>
Tue, 2 Oct 2018 12:46:51 +0000 (14:46 +0200)
committerMark Wielaard <mark@klomp.org>
Sat, 13 Oct 2018 20:54:51 +0000 (22:54 +0200)
This adds support for ADD and SUB relocations as seen on RISC-V.

Signed-off-by: Andreas Schwab <schwab@suse.de>
25 files changed:
backends/ChangeLog
backends/aarch64_symbol.c
backends/alpha_symbol.c
backends/arm_symbol.c
backends/bpf_symbol.c
backends/i386_symbol.c
backends/ia64_symbol.c
backends/m68k_symbol.c
backends/ppc64_symbol.c
backends/ppc_symbol.c
backends/riscv_symbol.c
backends/s390_symbol.c
backends/sh_symbol.c
backends/sparc_symbol.c
backends/tilegx_symbol.c
backends/x86_64_symbol.c
libdwfl/ChangeLog
libdwfl/relocate.c
libebl/ChangeLog
libebl/ebl-hooks.h
libebl/eblopenbackend.c
libebl/eblrelocsimpletype.c
libebl/libebl.h
src/ChangeLog
src/strip.c

index fdff302..a7434dd 100644 (file)
@@ -1,3 +1,23 @@
+2018-10-02  Andreas Schwab  <schwab@suse.de>
+
+       * riscv_symbol.c (riscv_reloc_simple_type): Add parameter addsub.
+       Set it for ADD and SUB relocations.
+       * aarch64_symbol.c (aarch64_reloc_simple_type): Add and ignore
+       third parameter.
+       * alpha_symbol.c (alpha_reloc_simple_type): Likewise.
+       * arm_symbol.c (arm_reloc_simple_type): Likewise.
+       * bpf_symbol.c (bpf_reloc_simple_type): Likewise.
+       * i386_symbol.c (i386_reloc_simple_type): Likewise.
+       * ia64_symbol.c (ia64_reloc_simple_type): Likewise.
+       * m68k_symbol.c (m68k_reloc_simple_type): Likewise.
+       * ppc64_symbol.c (ppc64_reloc_simple_type): Likewise.
+       * ppc_symbol.c (ppc_reloc_simple_type): Likewise.
+       * s390_symbol.c (s390_reloc_simple_type): Likewise.
+       * sh_symbol.c (sh_reloc_simple_type): Likewise.
+       * sparc_symbol.c (sparc_reloc_simple_type): Likewise.
+       * tilegx_symbol.c (tilegx_reloc_simple_type): Likewise.
+       * x86_64_symbol.c (x86_64_reloc_simple_type): Likewise.
+
 2018-09-12  Mark Wielaard  <mark@klomp.org>
 
        * ppc64_init.c (ppc64_init): Use elf_getshdrstrndx.
index dfd755a..e30c409 100644 (file)
@@ -40,7 +40,8 @@
 
 /* Check for the simple reloc types.  */
 Elf_Type
-aarch64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+aarch64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+                          int *addsub __attribute__ ((unused)))
 {
   switch (type)
     {
index b7f7c17..53a9e7b 100644 (file)
@@ -61,7 +61,8 @@ alpha_dynamic_tag_check (int64_t tag)
 
 /* Check for the simple reloc types.  */
 Elf_Type
-alpha_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+alpha_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+                        int *addsub __attribute__ ((unused)))
 {
   switch (type)
     {
index 3edda72..c8e1d7f 100644 (file)
@@ -109,7 +109,8 @@ arm_machine_flag_check (GElf_Word flags)
 
 /* Check for the simple reloc types.  */
 Elf_Type
-arm_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+arm_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+                      int *addsub __attribute__ ((unused)))
 {
   switch (type)
     {
index c9856f2..85c948a 100644 (file)
@@ -40,7 +40,8 @@
 
 /* Check for the simple reloc types.  */
 Elf_Type
-bpf_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+bpf_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+                      int *addsub __attribute__ ((unused)))
 {
   switch (type)
     {
index 7dbf899..a4b6ec0 100644 (file)
@@ -49,7 +49,8 @@ i386_gotpc_reloc_check (Elf *elf __attribute__ ((unused)), int type)
 
 /* Check for the simple reloc types.  */
 Elf_Type
-i386_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+i386_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+                       int *addsub __attribute__ ((unused)))
 {
   switch (type)
     {
index f928b0b..0c038f0 100644 (file)
@@ -115,7 +115,8 @@ ia64_section_type_name (int type,
 
 /* Check for the simple reloc types.  */
 Elf_Type
-ia64_reloc_simple_type (Ebl *ebl, int type)
+ia64_reloc_simple_type (Ebl *ebl, int type,
+                       int *addsub __attribute__ ((unused)))
 {
   switch (type)
     {
index 269d12e..9551cdf 100644 (file)
@@ -54,7 +54,8 @@ m68k_gotpc_reloc_check (Elf *elf __attribute__ ((unused)), int type)
 
 /* Check for the simple reloc types.  */
 Elf_Type
-m68k_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+m68k_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+                       int *addsub __attribute__ ((unused)))
 {
   switch (type)
     {
index 40ba4f7..81b94cf 100644 (file)
@@ -42,7 +42,8 @@
 
 /* Check for the simple reloc types.  */
 Elf_Type
-ppc64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+ppc64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+                        int *addsub __attribute__ ((unused)))
 {
   switch (type)
     {
index 35b1431..5a169d5 100644 (file)
@@ -42,7 +42,8 @@
 
 /* Check for the simple reloc types.  */
 Elf_Type
-ppc_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+ppc_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+                      int *addsub __attribute__ ((unused)))
 {
   switch (type)
     {
index 866a2d7..c34b770 100644 (file)
 
 /* Check for the simple reloc types.  */
 Elf_Type
-riscv_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+riscv_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+                        int *addsub)
 {
   switch (type)
     {
+    case R_RISCV_SET8:
+      return ELF_T_BYTE;
+    case R_RISCV_SET16:
+      return ELF_T_HALF;
     case R_RISCV_32:
+    case R_RISCV_SET32:
       return ELF_T_WORD;
     case R_RISCV_64:
       return ELF_T_XWORD;
+    case R_RISCV_ADD16:
+      *addsub = 1;
+      return ELF_T_HALF;
+    case R_RISCV_SUB16:
+      *addsub = -1;
+      return ELF_T_HALF;
+    case R_RISCV_ADD32:
+      *addsub = 1;
+      return ELF_T_WORD;
+    case R_RISCV_SUB32:
+      *addsub = -1;
+      return ELF_T_WORD;
+    case R_RISCV_ADD64:
+      *addsub = 1;
+      return ELF_T_XWORD;
+    case R_RISCV_SUB64:
+      *addsub = -1;
+      return ELF_T_XWORD;
     default:
       return ELF_T_NUM;
     }
index a0a4faf..f91e137 100644 (file)
@@ -38,7 +38,8 @@
 
 /* Check for the simple reloc types.  */
 Elf_Type
-s390_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+s390_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+                       int *addsub __attribute__ ((unused)))
 {
   switch (type)
     {
index 8101e96..2761d92 100644 (file)
@@ -47,7 +47,8 @@ sh_gotpc_reloc_check (Elf *elf __attribute__ ((unused)), int type)
 
 /* Check for the simple reloc types.  */
 Elf_Type
-sh_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+sh_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+                     int *addsub __attribute__ ((unused)))
 {
   switch (type)
     {
index ec11dc9..e8ee391 100644 (file)
@@ -39,7 +39,8 @@
 
 /* Check for the simple reloc types.  */
 Elf_Type
-sparc_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+sparc_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+                        int *addsub __attribute__ ((unused)))
 {
   switch (type)
     {
index b653326..62a4690 100644 (file)
@@ -39,7 +39,8 @@
 
 /* Check for the simple reloc types.  */
 Elf_Type
-tilegx_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+tilegx_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+                         int *addsub __attribute__ ((unused)))
 {
   switch (type)
     {
index 1622461..e07b180 100644 (file)
@@ -40,7 +40,8 @@
 
 /* Check for the simple reloc types.  */
 Elf_Type
-x86_64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+x86_64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+                         int *addsub __attribute__ ((unused)))
 {
   switch (type)
     {
index 5e9b986..c5ea563 100644 (file)
@@ -1,3 +1,7 @@
+2018-10-02  Andreas Schwab  <schwab@suse.de>
+
+       * relocate.c (relocate): Handle ADD/SUB relocations.
+
 2018-09-13  Mark Wielaard  <mark@klomp.org>
 
        * dwfl_segment_report_module.c (dwfl_segment_report_module):
index 9afcdeb..58c5678 100644 (file)
@@ -338,7 +338,8 @@ relocate (Dwfl_Module * const mod,
         So we just pretend it's OK without further relocation.  */
       return DWFL_E_NOERROR;
 
-    Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype);
+    int addsub = 0;
+    Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype, &addsub);
     if (unlikely (type == ELF_T_NUM))
       return DWFL_E_BADRELTYPE;
 
@@ -383,6 +384,9 @@ relocate (Dwfl_Module * const mod,
       {
 #define DO_TYPE(NAME, Name)                    \
        case ELF_T_##NAME:                      \
+         if (addsub != 0 && addend == NULL)    \
+           /* These do not make sense with SHT_REL.  */ \
+           return DWFL_E_BADRELTYPE;           \
          size = sizeof (GElf_##Name);          \
        break
        TYPES;
@@ -417,11 +421,24 @@ relocate (Dwfl_Module * const mod,
       {
        /* For the addend form, we have the value already.  */
        value += *addend;
+       /* For ADD/SUB relocations we need to fetch the section
+          contents.  */
+       if (addsub != 0)
+         {
+           Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata,
+                                        ehdr->e_ident[EI_DATA]);
+           if (d == NULL)
+             return DWFL_E_LIBELF;
+           assert (d == &tmpdata);
+         }
        switch (type)
          {
 #define DO_TYPE(NAME, Name)                    \
            case ELF_T_##NAME:                  \
-             tmpbuf.Name = value;              \
+             if (addsub != 0)                  \
+               tmpbuf.Name += value * addsub;  \
+             else                              \
+               tmpbuf.Name = value;            \
            break
            TYPES;
 #undef DO_TYPE
index d36a268..aec848b 100644 (file)
@@ -1,3 +1,10 @@
+2018-10-02  Andreas Schwab  <schwab@suse.de>
+
+       * ebl-hooks.h (EBLHOOK(reloc_simple_type)): Add third parameter.
+       * libebl.h (ebl_reloc_simple_type): Likewise.
+       * eblopenbackend.c (default_reloc_simple_type): Likewise.
+       * eblrelocsimpletype.c (ebl_reloc_simple_type): Pass it down.
+
 2018-09-12  Mark Wielaard  <mark@klomp.org>
 
        * eblsectionstripp.c (ebl_section_strip_p): Drop ehdr argument.
index 7a355cd..1e7960b 100644 (file)
@@ -33,7 +33,7 @@ const char *EBLHOOK(reloc_type_name) (int, char *, size_t);
 bool EBLHOOK(reloc_type_check) (int);
 
 /* Check if relocation type is for simple absolute relocations.  */
-Elf_Type EBLHOOK(reloc_simple_type) (Ebl *, int);
+Elf_Type EBLHOOK(reloc_simple_type) (Ebl *, int, int *);
 
 /* Check relocation type use.  */
 bool EBLHOOK(reloc_valid_use) (Elf *, int);
index f5b3de2..d54b720 100644 (file)
@@ -145,7 +145,7 @@ static const struct
 static const char *default_reloc_type_name (int ignore, char *buf, size_t len);
 static bool default_reloc_type_check (int ignore);
 static bool default_reloc_valid_use (Elf *elf, int ignore);
-static Elf_Type default_reloc_simple_type (Ebl *ebl, int ignore);
+static Elf_Type default_reloc_simple_type (Ebl *ebl, int ignore, int *addsub);
 static bool default_gotpc_reloc_check (Elf *elf, int ignore);
 static const char *default_segment_type_name (int ignore, char *buf,
                                              size_t len);
@@ -452,7 +452,8 @@ default_reloc_valid_use (Elf *elf __attribute__ ((unused)),
 
 static Elf_Type
 default_reloc_simple_type (Ebl *eh __attribute__ ((unused)),
-                          int ignore __attribute__ ((unused)))
+                          int ignore __attribute__ ((unused)),
+                          int *addsub __attribute__ ((unused)))
 {
   return ELF_T_NUM;
 }
index 9bd2928..1229280 100644 (file)
@@ -34,7 +34,7 @@
 
 
 Elf_Type
-ebl_reloc_simple_type (Ebl *ebl, int reloc)
+ebl_reloc_simple_type (Ebl *ebl, int reloc, int *addsub)
 {
-  return ebl != NULL ? ebl->reloc_simple_type (ebl, reloc) : ELF_T_NUM;
+  return ebl != NULL ? ebl->reloc_simple_type (ebl, reloc, addsub) : ELF_T_NUM;
 }
index 5abc02d..a34fe48 100644 (file)
@@ -99,8 +99,10 @@ extern bool ebl_reloc_type_check (Ebl *ebl, int reloc);
 extern bool ebl_reloc_valid_use (Ebl *ebl, int reloc);
 
 /* Check if relocation type is for simple absolute relocations.
-   Return ELF_T_{BYTE,HALF,SWORD,SXWORD} for a simple type, else ELF_T_NUM.  */
-extern Elf_Type ebl_reloc_simple_type (Ebl *ebl, int reloc);
+   Return ELF_T_{BYTE,HALF,SWORD,SXWORD} for a simple type, else ELF_T_NUM.
+   If the relocation type is an ADD or SUB relocation, set *ADDSUB to 1 or -1,
+   resp.  */
+extern Elf_Type ebl_reloc_simple_type (Ebl *ebl, int reloc, int *addsub);
 
 /* Return true if the symbol type is that referencing the GOT.  E.g.,
    R_386_GOTPC.  */
index 6a702ee..7b59ed6 100644 (file)
@@ -1,3 +1,7 @@
+2018-10-02  Andreas Schwab  <schwab@suse.de>
+
+       * strip.c (handle_elf): Handle ADD/SUB relocation.
+
 2018-09-13  Mark Wielaard  <mark@klomp.org>
 
        * readelf.c (print_shdr): Get number of section with elf_getshdrnum.
index 4a3db1b..1f7b3ca 100644 (file)
@@ -2030,7 +2030,8 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
                  return true;
 
                /* We only do simple absolute relocations.  */
-               Elf_Type type = ebl_reloc_simple_type (ebl, rtype);
+               int addsub = 0;
+               Elf_Type type = ebl_reloc_simple_type (ebl, rtype, &addsub);
                if (type == ELF_T_NUM)
                  return false;
 
@@ -2109,6 +2110,17 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
                        /* For SHT_RELA sections we just take the
                           given addend and add it to the value.  */
                        value += addend;
+                       /* For ADD/SUB relocations we need to fetch the
+                          current section contents.  */
+                       if (addsub != 0)
+                         {
+                           Elf_Data *d = gelf_xlatetom (debugelf, &tmpdata,
+                                                        &rdata,
+                                                        ehdr->e_ident[EI_DATA]);
+                           if (d == NULL)
+                             INTERNAL_ERROR (fname);
+                           assert (d == &tmpdata);
+                         }
                      }
                    else
                      {
@@ -2125,9 +2137,12 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
 
                    switch (type)
                      {
-#define DO_TYPE(NAME, Name)                                    \
-                       case ELF_T_##NAME:                      \
-                         tmpbuf.Name += (GElf_##Name) value;   \
+#define DO_TYPE(NAME, Name)                                     \
+                       case ELF_T_##NAME:                       \
+                         if (addsub < 0)                        \
+                           tmpbuf.Name -= (GElf_##Name) value; \
+                         else                                   \
+                           tmpbuf.Name += (GElf_##Name) value; \
                          break;
                        TYPES;
 #undef DO_TYPE