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."