From 2876b3b648f665736ac9c879d34de5e3866ba8f9 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Tue, 2 Oct 2018 14:46:51 +0200 Subject: [PATCH] Handle ADD/SUB relocations This adds support for ADD and SUB relocations as seen on RISC-V. Signed-off-by: Andreas Schwab --- backends/ChangeLog | 20 ++++++++++++++++++++ backends/aarch64_symbol.c | 3 ++- backends/alpha_symbol.c | 3 ++- backends/arm_symbol.c | 3 ++- backends/bpf_symbol.c | 3 ++- backends/i386_symbol.c | 3 ++- backends/ia64_symbol.c | 3 ++- backends/m68k_symbol.c | 3 ++- backends/ppc64_symbol.c | 3 ++- backends/ppc_symbol.c | 3 ++- backends/riscv_symbol.c | 26 +++++++++++++++++++++++++- backends/s390_symbol.c | 3 ++- backends/sh_symbol.c | 3 ++- backends/sparc_symbol.c | 3 ++- backends/tilegx_symbol.c | 3 ++- backends/x86_64_symbol.c | 3 ++- libdwfl/ChangeLog | 4 ++++ libdwfl/relocate.c | 21 +++++++++++++++++++-- libebl/ChangeLog | 7 +++++++ libebl/ebl-hooks.h | 2 +- libebl/eblopenbackend.c | 5 +++-- libebl/eblrelocsimpletype.c | 4 ++-- libebl/libebl.h | 6 ++++-- src/ChangeLog | 4 ++++ src/strip.c | 23 +++++++++++++++++++---- 25 files changed, 136 insertions(+), 28 deletions(-) diff --git a/backends/ChangeLog b/backends/ChangeLog index fdff302..a7434dd 100644 --- a/backends/ChangeLog +++ b/backends/ChangeLog @@ -1,3 +1,23 @@ +2018-10-02 Andreas Schwab + + * 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 * ppc64_init.c (ppc64_init): Use elf_getshdrstrndx. diff --git a/backends/aarch64_symbol.c b/backends/aarch64_symbol.c index dfd755a..e30c409 100644 --- a/backends/aarch64_symbol.c +++ b/backends/aarch64_symbol.c @@ -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) { diff --git a/backends/alpha_symbol.c b/backends/alpha_symbol.c index b7f7c17..53a9e7b 100644 --- a/backends/alpha_symbol.c +++ b/backends/alpha_symbol.c @@ -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) { diff --git a/backends/arm_symbol.c b/backends/arm_symbol.c index 3edda72..c8e1d7f 100644 --- a/backends/arm_symbol.c +++ b/backends/arm_symbol.c @@ -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) { diff --git a/backends/bpf_symbol.c b/backends/bpf_symbol.c index c9856f2..85c948a 100644 --- a/backends/bpf_symbol.c +++ b/backends/bpf_symbol.c @@ -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) { diff --git a/backends/i386_symbol.c b/backends/i386_symbol.c index 7dbf899..a4b6ec0 100644 --- a/backends/i386_symbol.c +++ b/backends/i386_symbol.c @@ -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) { diff --git a/backends/ia64_symbol.c b/backends/ia64_symbol.c index f928b0b..0c038f0 100644 --- a/backends/ia64_symbol.c +++ b/backends/ia64_symbol.c @@ -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) { diff --git a/backends/m68k_symbol.c b/backends/m68k_symbol.c index 269d12e..9551cdf 100644 --- a/backends/m68k_symbol.c +++ b/backends/m68k_symbol.c @@ -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) { diff --git a/backends/ppc64_symbol.c b/backends/ppc64_symbol.c index 40ba4f7..81b94cf 100644 --- a/backends/ppc64_symbol.c +++ b/backends/ppc64_symbol.c @@ -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) { diff --git a/backends/ppc_symbol.c b/backends/ppc_symbol.c index 35b1431..5a169d5 100644 --- a/backends/ppc_symbol.c +++ b/backends/ppc_symbol.c @@ -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) { diff --git a/backends/riscv_symbol.c b/backends/riscv_symbol.c index 866a2d7..c34b770 100644 --- a/backends/riscv_symbol.c +++ b/backends/riscv_symbol.c @@ -40,14 +40,38 @@ /* 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; } diff --git a/backends/s390_symbol.c b/backends/s390_symbol.c index a0a4faf..f91e137 100644 --- a/backends/s390_symbol.c +++ b/backends/s390_symbol.c @@ -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) { diff --git a/backends/sh_symbol.c b/backends/sh_symbol.c index 8101e96..2761d92 100644 --- a/backends/sh_symbol.c +++ b/backends/sh_symbol.c @@ -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) { diff --git a/backends/sparc_symbol.c b/backends/sparc_symbol.c index ec11dc9..e8ee391 100644 --- a/backends/sparc_symbol.c +++ b/backends/sparc_symbol.c @@ -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) { diff --git a/backends/tilegx_symbol.c b/backends/tilegx_symbol.c index b653326..62a4690 100644 --- a/backends/tilegx_symbol.c +++ b/backends/tilegx_symbol.c @@ -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) { diff --git a/backends/x86_64_symbol.c b/backends/x86_64_symbol.c index 1622461..e07b180 100644 --- a/backends/x86_64_symbol.c +++ b/backends/x86_64_symbol.c @@ -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) { diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 5e9b986..c5ea563 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,7 @@ +2018-10-02 Andreas Schwab + + * relocate.c (relocate): Handle ADD/SUB relocations. + 2018-09-13 Mark Wielaard * dwfl_segment_report_module.c (dwfl_segment_report_module): diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c index 9afcdeb..58c5678 100644 --- a/libdwfl/relocate.c +++ b/libdwfl/relocate.c @@ -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 diff --git a/libebl/ChangeLog b/libebl/ChangeLog index d36a268..aec848b 100644 --- a/libebl/ChangeLog +++ b/libebl/ChangeLog @@ -1,3 +1,10 @@ +2018-10-02 Andreas Schwab + + * 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 * eblsectionstripp.c (ebl_section_strip_p): Drop ehdr argument. diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h index 7a355cd..1e7960b 100644 --- a/libebl/ebl-hooks.h +++ b/libebl/ebl-hooks.h @@ -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); diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c index f5b3de2..d54b720 100644 --- a/libebl/eblopenbackend.c +++ b/libebl/eblopenbackend.c @@ -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; } diff --git a/libebl/eblrelocsimpletype.c b/libebl/eblrelocsimpletype.c index 9bd2928..1229280 100644 --- a/libebl/eblrelocsimpletype.c +++ b/libebl/eblrelocsimpletype.c @@ -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; } diff --git a/libebl/libebl.h b/libebl/libebl.h index 5abc02d..a34fe48 100644 --- a/libebl/libebl.h +++ b/libebl/libebl.h @@ -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. */ diff --git a/src/ChangeLog b/src/ChangeLog index 6a702ee..7b59ed6 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2018-10-02 Andreas Schwab + + * strip.c (handle_elf): Handle ADD/SUB relocation. + 2018-09-13 Mark Wielaard * readelf.c (print_shdr): Get number of section with elf_getshdrnum. diff --git a/src/strip.c b/src/strip.c index 4a3db1b..1f7b3ca 100644 --- a/src/strip.c +++ b/src/strip.c @@ -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 -- 2.7.4