This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] 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>
---
 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  <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 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  <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 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  <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 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  <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 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."


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]