]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
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 fdff30219491c1bda2666d103085428340b007ee..a7434dd2d3ed6f1eaa9bb3ac83b5a8bdb4c71a37 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 dfd755a54b83b325f3cbfcb9c201f5117c64fbed..e30c409d74f90f6dfeb27708991969fe587ca626 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 b7f7c17a007dd633a6918c393385660a6d0fce3a..53a9e7b7b493475e3b8b2d241cfd3711f94d5ae3 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 3edda7247ef1ff62aa3588e0369b8c64b4f92104..c8e1d7f914b0ea9a135adb5bb494e4ce4bc53c0e 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 c9856f263809eaa28903ba7227a4ecc0d8b18439..85c948ab81165c6c5e0375b34ef2e86b36457653 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 7dbf899fd2a20598b77717fe318dba0fef364a41..a4b6ec08b6dc0f8d8109690daa3b5ca10da3861b 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 f928b0b7f75461558c9d1e9c7f373ae1bf0aaa45..0c038f0dc83101e9d2f396e0ce5eadb7cb142b4f 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 269d12e5bbe442d738f24d723fab9ca1199e36f6..9551cdfefd0ea401eb2527d741ec50c9afbab659 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 40ba4f74496b9ab0ab945bf5a5b0a10937752bd2..81b94cfd9f4a48e4c9c04a71ef06e9dd2be7abaa 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 35b143190cc0f8797b833b35dc6a15d93e038a8a..5a169d54109eb1071f0757eb38ba5aa6b3449938 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 866a2d7a4b1722aa0789bf5011eec4dd60a7c8cb..c34b770206cef2288f7b12647dff124d81ddfc57 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 a0a4fafaf577541e1eb948ac6871c56223ead9c3..f91e13735e9ccd66919589fb1f1b0a402060b338 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 8101e96f519e1a5691d81a34ab0d3c7d0a124280..2761d92c20f7ab389ebba5e26caad03243f5516f 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 ec11dc9731af90a1a53edd0e8608f09dd4b5f150..e8ee39112be447135b2a833910ef8b64f914ffc7 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 b6533266a649a303261e988b6d3edfb315af7704..62a469070b207d8c3f77a6f838f091864670b872 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 1622461d395b8f0d0afcf4a1494903ff4c2d2799..e07b1806d5e7d874e3c670f66477f54f65e66f96 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 5e9b986d02b1728ba7d291dadc3e33bdbd14e564..c5ea56342565bc62e3477aaed3bde171a8a8b8b4 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 9afcdebecc05b157baabd8f3ce0c2067b43a4637..58c56786dda682ceef5cd0760f079b95094f1b63 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 d36a268158b9c5ea96e6941dbf2a1d9e5d548880..aec848b9cd8db6f339c4c508aaf3ef1f63769e42 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 7a355cd1296638b2e755ec0e825ea011bf639e00..1e7960b8964ce9dbeeb06dfa32d314593fb54e4e 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 f5b3de29f71f0fc0ca43d958eca11b6e4634e997..d54b720756c375afd458d6daa5e48fbc85b32fb2 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 9bd29285a3b0f033beebb77aee069aa5bd7c2452..12292804df92f1ee55e9b5ac0d5e1be7e1f880d4 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 5abc02d87aa3e4075c6e67a184456d78e11c75fb..a34fe48ddc4a305a6dc970c204c1e114b3106689 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 6a702ee1cca26b58ff56753656a7ebeea01393fa..7b59ed60b97e83b5bbeb7e3ce90a13227015a39d 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 4a3db1b55efaee091d06db3f54262948da19348e..1f7b3cabc0420c5930c7bc47a5338424d531fdea 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