From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 69023 invoked by alias); 2 Oct 2018 12:46:58 -0000 Mailing-List: contact elfutils-devel-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Post: List-Help: List-Subscribe: Sender: elfutils-devel-owner@sourceware.org Received: (qmail 69012 invoked by uid 89); 2 Oct 2018 12:46:57 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Checked: by ClamAV 0.100.1 on sourceware.org X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,SPF_PASS autolearn=ham version=3.3.2 spammy=HTo:U*mark, relocate, 1097, 1098 X-Spam-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,SPF_PASS autolearn=ham version=3.3.2 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on sourceware.org X-Spam-Level: X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 02 Oct 2018 12:46:55 +0000 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id A7CAAAFCC; Tue, 2 Oct 2018 12:46:52 +0000 (UTC) From: Andreas Schwab To: Mark Wielaard Cc: elfutils-devel@sourceware.org Subject: [PATCH] Handle ADD/SUB relocations References: <20180614232812.GG7539@wildebeest.org> <1529493408.12946.131.camel@klomp.org> <1529499550.12946.137.camel@klomp.org> <1529527688.12946.141.camel@klomp.org> <1532620979.12909.38.camel@klomp.org> X-Yow: I love FRUIT PICKERS!! Date: Tue, 02 Oct 2018 12:46:00 -0000 In-Reply-To: <1532620979.12909.38.camel@klomp.org> (Mark Wielaard's message of "Thu, 26 Jul 2018 18:02:59 +0200") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-SW-Source: 2018-q4/txt/msg00000.txt.bz2 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 fdff302194..a7434dd2d3 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 dfd755a54b..e30c409d74 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 b7f7c17a00..53a9e7b7b4 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 3edda7247e..c8e1d7f914 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 c9856f2638..85c948ab81 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 7dbf899fd2..a4b6ec08b6 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 f928b0b7f7..0c038f0dc8 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 269d12e5bb..9551cdfefd 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 40ba4f7449..81b94cfd9f 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 35b143190c..5a169d5410 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 866a2d7a4b..c34b770206 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 a0a4fafaf5..f91e13735e 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 8101e96f51..2761d92c20 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 ec11dc9731..e8ee39112b 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 b6533266a6..62a469070b 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 1622461d39..e07b1806d5 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 5e9b986d02..c5ea563425 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 9afcdebecc..58c56786dd 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 d36a268158..aec848b9cd 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 7a355cd129..1e7960b896 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 f5b3de29f7..d54b720756 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 9bd29285a3..12292804df 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 5abc02d87a..a34fe48ddc 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 6a702ee1cc..7b59ed60b9 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 4a3db1b55e..1f7b3cabc0 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.19.0 -- Andreas Schwab, SUSE Labs, schwab@suse.de GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different."