summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@suse.de>2018-10-02 14:46:51 +0200
committerMark Wielaard <mark@klomp.org>2018-10-13 22:54:51 +0200
commit2876b3b648f665736ac9c879d34de5e3866ba8f9 (patch)
treebe631dee293e01847e3eea43343b0d249a7532c6
parent69d6e67eee30c483ba53a8e1da1b3568033e3dde (diff)
Handle ADD/SUB relocations
This adds support for ADD and SUB relocations as seen on RISC-V. Signed-off-by: Andreas Schwab <schwab@suse.de>
-rw-r--r--backends/ChangeLog20
-rw-r--r--backends/aarch64_symbol.c3
-rw-r--r--backends/alpha_symbol.c3
-rw-r--r--backends/arm_symbol.c3
-rw-r--r--backends/bpf_symbol.c3
-rw-r--r--backends/i386_symbol.c3
-rw-r--r--backends/ia64_symbol.c3
-rw-r--r--backends/m68k_symbol.c3
-rw-r--r--backends/ppc64_symbol.c3
-rw-r--r--backends/ppc_symbol.c3
-rw-r--r--backends/riscv_symbol.c26
-rw-r--r--backends/s390_symbol.c3
-rw-r--r--backends/sh_symbol.c3
-rw-r--r--backends/sparc_symbol.c3
-rw-r--r--backends/tilegx_symbol.c3
-rw-r--r--backends/x86_64_symbol.c3
-rw-r--r--libdwfl/ChangeLog4
-rw-r--r--libdwfl/relocate.c21
-rw-r--r--libebl/ChangeLog7
-rw-r--r--libebl/ebl-hooks.h2
-rw-r--r--libebl/eblopenbackend.c5
-rw-r--r--libebl/eblrelocsimpletype.c4
-rw-r--r--libebl/libebl.h6
-rw-r--r--src/ChangeLog4
-rw-r--r--src/strip.c23
25 files changed, 136 insertions, 28 deletions
diff --git a/backends/ChangeLog b/backends/ChangeLog
index fdff3021..a7434dd2 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -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.
diff --git a/backends/aarch64_symbol.c b/backends/aarch64_symbol.c
index dfd755a5..e30c409d 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 b7f7c17a..53a9e7b7 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 3edda724..c8e1d7f9 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 c9856f26..85c948ab 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 7dbf899f..a4b6ec08 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 f928b0b7..0c038f0d 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 269d12e5..9551cdfe 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 40ba4f74..81b94cfd 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 35b14319..5a169d54 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 866a2d7a..c34b7702 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 a0a4fafa..f91e1373 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 8101e96f..2761d92c 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 ec11dc97..e8ee3911 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 b6533266..62a46907 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 1622461d..e07b1806 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 5e9b986d..c5ea5634 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -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):
diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c
index 9afcdebe..58c56786 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 d36a2681..aec848b9 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -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.
diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h
index 7a355cd1..1e7960b8 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 f5b3de29..d54b7207 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 9bd29285..12292804 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 5abc02d8..a34fe48d 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 6a702ee1..7b59ed60 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -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.
diff --git a/src/strip.c b/src/strip.c
index 4a3db1b5..1f7b3cab 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