How about this, does it look reasonable?  It doesn't handle SET6/SUB6
yet, and eu-readelf -wframe doesn't agree with readelf -wf, so this is
only a RFC.

Andreas.

diff --git a/backends/riscv_symbol.c b/backends/riscv_symbol.c
index dce8e3586b..866be8f093 100644
--- a/backends/riscv_symbol.c
+++ b/backends/riscv_symbol.c
@@ -44,10 +44,27 @@ riscv_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), 
int type)
 {
   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:
+      return ELF_T_ADD_HALF;
+    case R_RISCV_SUB16:
+      return ELF_T_SUB_HALF;
+    case R_RISCV_ADD32:
+      return ELF_T_ADD_WORD;
+    case R_RISCV_SUB32:
+      return ELF_T_SUB_WORD;
+    case R_RISCV_ADD64:
+      return ELF_T_ADD_XWORD;
+    case R_RISCV_SUB64:
+      return ELF_T_SUB_XWORD;
     default:
       return ELF_T_NUM;
     }
diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c
index 9afcdebecc..1c4a1bade2 100644
--- a/libdwfl/relocate.c
+++ b/libdwfl/relocate.c
@@ -379,9 +379,18 @@ relocate (Dwfl_Module * const mod,
     DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword);                      \
     DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
     size_t size;
+    bool is_add_sub = false;
     switch (type)
       {
 #define DO_TYPE(NAME, Name)                    \
+       case ELF_T_ADD_##NAME:                  \
+       case ELF_T_SUB_##NAME:                  \
+         if (addend == NULL)                   \
+           /* These do not make sense with SHT_REL.  */ \
+           return DWFL_E_BADRELTYPE;           \
+         is_add_sub = true;                    \
+         size = sizeof (GElf_##Name);          \
+         break;                                \
        case ELF_T_##NAME:                      \
          size = sizeof (GElf_##Name);          \
        break
@@ -417,9 +426,23 @@ relocate (Dwfl_Module * const mod,
       {
        /* For the addend form, we have the value already.  */
        value += *addend;
+       if (is_add_sub)
+         {
+           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_ADD_##NAME:              \
+             tmpbuf.Name += value;             \
+             break;                            \
+           case ELF_T_SUB_##NAME:              \
+             tmpbuf.Name -= value;             \
+             break;                            \
            case ELF_T_##NAME:                  \
              tmpbuf.Name = value;              \
            break
diff --git a/libelf/gelf_fsize.c b/libelf/gelf_fsize.c
index 0c509265cb..faa6d6fd4b 100644
--- a/libelf/gelf_fsize.c
+++ b/libelf/gelf_fsize.c
@@ -52,6 +52,18 @@ const size_t __libelf_type_sizes[EV_NUM - 1][ELFCLASSNUM - 
1][ELF_T_NUM] =
       [ELF_T_SWORD]    = ELFW2(LIBELFBITS, FSZ_SWORD),                       \
       [ELF_T_XWORD]    = ELFW2(LIBELFBITS, FSZ_XWORD),                       \
       [ELF_T_SXWORD]   = ELFW2(LIBELFBITS, FSZ_SXWORD),                      \
+      [ELF_T_ADD_BYTE] = 1,                                                  \
+      [ELF_T_ADD_HALF] = ELFW2(LIBELFBITS, FSZ_HALF),                        \
+      [ELF_T_ADD_WORD] = ELFW2(LIBELFBITS, FSZ_WORD),                        \
+      [ELF_T_ADD_SWORD]        = ELFW2(LIBELFBITS, FSZ_SWORD),                 
      \
+      [ELF_T_ADD_XWORD]        = ELFW2(LIBELFBITS, FSZ_XWORD),                 
      \
+      [ELF_T_ADD_SXWORD] = ELFW2(LIBELFBITS, FSZ_SXWORD),                    \
+      [ELF_T_SUB_BYTE] = 1,                                                  \
+      [ELF_T_SUB_HALF] = ELFW2(LIBELFBITS, FSZ_HALF),                        \
+      [ELF_T_SUB_WORD] = ELFW2(LIBELFBITS, FSZ_WORD),                        \
+      [ELF_T_SUB_SWORD]        = ELFW2(LIBELFBITS, FSZ_SWORD),                 
      \
+      [ELF_T_SUB_XWORD]        = ELFW2(LIBELFBITS, FSZ_XWORD),                 
      \
+      [ELF_T_SUB_SXWORD] = ELFW2(LIBELFBITS, FSZ_SXWORD),                    \
       [ELF_T_EHDR]     = sizeof (ElfW2(LIBELFBITS, Ext_Ehdr)),               \
       [ELF_T_SHDR]     = sizeof (ElfW2(LIBELFBITS, Ext_Shdr)),               \
       [ELF_T_SYM]      = sizeof (ElfW2(LIBELFBITS, Ext_Sym)),                \
diff --git a/libelf/libelf.h b/libelf/libelf.h
index 547c0f5081..38eeea31ab 100644
--- a/libelf/libelf.h
+++ b/libelf/libelf.h
@@ -117,6 +117,18 @@ typedef enum
   ELF_T_GNUHASH,               /* GNU-style hash section.  */
   ELF_T_AUXV,                  /* Elf32_auxv_t, Elf64_auxv_t, ... */
   ELF_T_CHDR,                  /* Compressed, Elf32_Chdr, Elf64_Chdr, ... */
+  ELF_T_ADD_BYTE,
+  ELF_T_SUB_BYTE,
+  ELF_T_ADD_HALF,
+  ELF_T_SUB_HALF,
+  ELF_T_ADD_WORD,
+  ELF_T_SUB_WORD,
+  ELF_T_ADD_SWORD,
+  ELF_T_SUB_SWORD,
+  ELF_T_ADD_XWORD,
+  ELF_T_SUB_XWORD,
+  ELF_T_ADD_SXWORD,
+  ELF_T_SUB_SXWORD,
   /* Keep this the last entry.  */
   ELF_T_NUM
 } Elf_Type;
diff --git a/src/strip.c b/src/strip.c
index 791347c1dd..32190344ba 100644
--- a/src/strip.c
+++ b/src/strip.c
@@ -1968,6 +1968,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const 
char *fname,
                if (ebl_debugscn_p (ebl, shdr_info[sec].name))
                  {
                    size_t size;
+                   bool is_add_sub;
 
 #define DO_TYPE(NAME, Name) GElf_##Name Name;
                    union { TYPES; } tmpbuf;
@@ -1976,9 +1977,16 @@ handle_elf (int fd, Elf *elf, const char *prefix, const 
char *fname,
                    switch (type)
                      {
 #define DO_TYPE(NAME, Name)                            \
+                       case ELF_T_ADD_##NAME:          \
+                       case ELF_T_SUB_##NAME:          \
+                         size = sizeof (GElf_##Name);  \
+                         tmpbuf.Name = 0;              \
+                         is_add_sub = true;            \
+                         break;                        \
                        case ELF_T_##NAME:              \
                          size = sizeof (GElf_##Name);  \
                          tmpbuf.Name = 0;              \
+                         is_add_sub = false;           \
                          break;
                        TYPES;
 #undef DO_TYPE
@@ -2024,6 +2032,15 @@ 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;
+                       if (is_add_sub)
+                         {
+                           Elf_Data *d = gelf_xlatetom (debugelf, &tmpdata,
+                                                        &rdata,
+                                                        
ehdr->e_ident[EI_DATA]);
+                           if (d == NULL)
+                             INTERNAL_ERROR (fname);
+                           assert (d == &tmpdata);
+                         }
                      }
                    else
                      {
@@ -2042,7 +2059,11 @@ handle_elf (int fd, Elf *elf, const char *prefix, const 
char *fname,
                      {
 #define DO_TYPE(NAME, Name)                                    \
                        case ELF_T_##NAME:                      \
+                       case ELF_T_ADD_##NAME:                  \
                          tmpbuf.Name += (GElf_##Name) value;   \
+                         break;                                \
+                       case ELF_T_SUB_##NAME:                  \
+                         tmpbuf.Name -= (GElf_##Name) value;   \
                          break;
                        TYPES;
 #undef DO_TYPE
-- 
2.18.0

-- 
Andreas Schwab, SUSE Labs, sch...@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

Reply via email to