All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
To: buildroot@busybox.net
Subject: [Buildroot] [git commit] package/binutils: fix xtensa PR ld/25861
Date: Thu, 23 Apr 2020 23:31:54 +0200	[thread overview]
Message-ID: <20200423211738.B63468FDF7@busybox.osuosl.org> (raw)

commit: https://git.buildroot.net/buildroot/commit/?id=f0291ef4aba0954542000f40bbf3c67641f33011
branch: https://git.buildroot.net/buildroot/commit/?id=refs/heads/master

Handle link-time relaxation of full 16-bit difference values correctly
in xtensa linker. This fixes the following kind of build errors:

.../five-point.cpp:338:(.debug_line+0x3b12):
       	dangerous relocation: overflow after relaxation

Backported from:
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff;h=30ce8e47fad9b057b6d7af9e1d43061126d34d20
Fixes:
http://autobuild.buildroot.net/results/67a5545779bbe8ca2b21da1f3ff2002053710ce1/
http://autobuild.buildroot.net/results/87f38998d2d60b6bce3128589973187ef9596e28/

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
---
 .../2.31.1/0019-xtensa-fix-PR-ld-25861.patch       | 376 ++++++++++++++++++
 .../2.32/0008-xtensa-fix-PR-ld-25861.patch         | 432 +++++++++++++++++++++
 .../2.33.1/0005-xtensa-fix-PR-ld-25861.patch       | 432 +++++++++++++++++++++
 3 files changed, 1240 insertions(+)

diff --git a/package/binutils/2.31.1/0019-xtensa-fix-PR-ld-25861.patch b/package/binutils/2.31.1/0019-xtensa-fix-PR-ld-25861.patch
new file mode 100644
index 0000000000..8ca8c965d2
--- /dev/null
+++ b/package/binutils/2.31.1/0019-xtensa-fix-PR-ld-25861.patch
@@ -0,0 +1,376 @@
+From c7a1d1f656c717394937a92cb970f0f4cecce128 Mon Sep 17 00:00:00 2001
+From: Max Filippov <jcmvbkbc@gmail.com>
+Date: Sun, 19 Apr 2020 19:04:41 -0700
+Subject: [PATCH] xtensa: fix PR ld/25861
+
+Introduce new relaxations XTENSA_PDIFF{8,16,32} for positive differences
+(subtracted symbol precedes diminished symbol) and XTENSA_NDIFF{8,16,32}
+for negative differences (subtracted symbol follows diminished symbol).
+Don't generate XTENSA_DIFF relocations in the assembler, generate
+XTENSA_PDIFF or XTENSA_NDIFF based on relative symbol position.
+
+Handle XTENSA_DIFF in BFD for compatibility with old object files.
+Handle XTENSA_PDIFF and XTENSA_NDIFF in BFD, treating difference value
+as unsigned.
+
+2020-04-22  Max Filippov  <jcmvbkbc@gmail.com>
+bfd/
+	* bfd-in2.h: Regenerated.
+	* elf32-xtensa.c (elf_howto_table): New entries for
+	R_XTENSA_PDIFF{8,16,32} and R_XTENSA_NDIFF{8,16,32}.
+	(elf_xtensa_reloc_type_lookup, elf_xtensa_do_reloc)
+	(relax_section): Add cases for R_XTENSA_PDIFF{8,16,32} and
+	R_XTENSA_NDIFF{8,16,32}.
+	* libbfd.h (bfd_reloc_code_real_names): Add names for
+	BFD_RELOC_XTENSA_PDIFF{8,16,32} and
+	BFD_RELOC_XTENSA_NDIFF{8,16,32}.
+	* reloc.c: Add documentation for BFD_RELOC_XTENSA_PDIFF{8,16,32}
+	and BFD_RELOC_XTENSA_NDIFF{8,16,32}.
+
+binutils/
+	* readelf.c (is_none_reloc): Recognize
+	BFD_RELOC_XTENSA_PDIFF{8,16,32} and
+	BFD_RELOC_XTENSA_NDIFF{8,16,32}.
+
+gas/
+	* config/tc-xtensa.c (md_apply_fix): Replace
+	BFD_RELOC_XTENSA_DIFF{8,16,32} generation with
+	BFD_RELOC_XTENSA_PDIFF{8,16,32} and
+	BFD_RELOC_XTENSA_NDIFF{8,16,32} generation.
+	* testsuite/gas/xtensa/loc.d: Replace BFD_RELOC_XTENSA_DIFF16
+	with BFD_RELOC_XTENSA_PDIFF16 in the expected output.
+
+include/
+	* elf/xtensa.h (elf_xtensa_reloc_type): New entries for
+	R_XTENSA_PDIFF{8,16,32} and R_XTENSA_NDIFF{8,16,32}.
+
+Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
+---
+Backported from: 30ce8e47fad9b057b6d7af9e1d43061126d34d20
+
+ bfd/bfd-in2.h                      | 20 ++++++-
+ bfd/elf32-xtensa.c                 | 89 +++++++++++++++++++++++++++++-
+ bfd/libbfd.h                       |  6 ++
+ bfd/reloc.c                        | 24 ++++++++
+ binutils/readelf.c                 |  8 ++-
+ gas/config/tc-xtensa.c             | 12 +++-
+ gas/testsuite/gas/xtensa/loc.d     |  2 +-
+ include/elf/xtensa.h               |  6 ++
+ 11 files changed, 160 insertions(+), 7 deletions(-)
+
+diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
+index 37114607b515..be6a30f57955 100644
+--- a/bfd/bfd-in2.h
++++ b/bfd/bfd-in2.h
+@@ -5217,7 +5217,9 @@ to one of its own internal functions or data structures.  */
+ PLT entries.  Otherwise, this is just a generic 32-bit relocation.  */
+   BFD_RELOC_XTENSA_PLT,
+ 
+-/* Xtensa relocations to mark the difference of two local symbols.
++/* Xtensa relocations for backward compatibility.  These have been replaced
++by BFD_RELOC_XTENSA_PDIFF and BFD_RELOC_XTENSA_NDIFF.
++Xtensa relocations to mark the difference of two local symbols.
+ These are only needed to support linker relaxation and can be ignored
+ when not relaxing.  The field is set to the value of the difference
+ assuming no relaxation.  The relocation encodes the position of the
+@@ -5291,6 +5293,22 @@ BFD_RELOC_XTENSA_ASM_EXPAND.  */
+   BFD_RELOC_XTENSA_TLS_ARG,
+   BFD_RELOC_XTENSA_TLS_CALL,
+ 
++/* Xtensa relocations to mark the difference of two local symbols.
++These are only needed to support linker relaxation and can be ignored
++when not relaxing.  The field is set to the value of the difference
++assuming no relaxation.  The relocation encodes the position of the
++subtracted symbol so the linker can determine whether to adjust the field
++value.  PDIFF relocations are used for positive differences, NDIFF
++relocations are used for negative differences.  The difference value
++is treated as unsigned with these relocation types, giving full
++8/16 value ranges.  */
++  BFD_RELOC_XTENSA_PDIFF8,
++  BFD_RELOC_XTENSA_PDIFF16,
++  BFD_RELOC_XTENSA_PDIFF32,
++  BFD_RELOC_XTENSA_NDIFF8,
++  BFD_RELOC_XTENSA_NDIFF16,
++  BFD_RELOC_XTENSA_NDIFF32,
++
+ /* 8 bit signed offset in (ix+d) or (iy+d).  */
+   BFD_RELOC_Z80_DISP8,
+ 
+diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
+index 473a9d76f289..fded42d52a9a 100644
+--- a/bfd/elf32-xtensa.c
++++ b/bfd/elf32-xtensa.c
+@@ -325,6 +325,20 @@ static reloc_howto_type elf_howto_table[] =
+   HOWTO (R_XTENSA_TLS_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+ 	 bfd_elf_xtensa_reloc, "R_XTENSA_TLS_CALL",
+ 	 FALSE, 0, 0, FALSE),
++
++  HOWTO (R_XTENSA_PDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF8", FALSE, 0, 0xff, FALSE),
++  HOWTO (R_XTENSA_PDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF16", FALSE, 0, 0xffff, FALSE),
++  HOWTO (R_XTENSA_PDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF32", FALSE, 0, 0xffffffff, FALSE),
++
++  HOWTO (R_XTENSA_NDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF8", FALSE, 0, 0xff, FALSE),
++  HOWTO (R_XTENSA_NDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF16", FALSE, 0, 0xffff, FALSE),
++  HOWTO (R_XTENSA_NDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF32", FALSE, 0, 0xffffffff, FALSE),
+ };
+ 
+ #if DEBUG_GEN_RELOC
+@@ -364,6 +378,30 @@ elf_xtensa_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+       TRACE ("BFD_RELOC_XTENSA_DIFF32");
+       return &elf_howto_table[(unsigned) R_XTENSA_DIFF32 ];
+ 
++    case BFD_RELOC_XTENSA_PDIFF8:
++      TRACE ("BFD_RELOC_XTENSA_PDIFF8");
++      return &elf_howto_table[(unsigned) R_XTENSA_PDIFF8 ];
++
++    case BFD_RELOC_XTENSA_PDIFF16:
++      TRACE ("BFD_RELOC_XTENSA_PDIFF16");
++      return &elf_howto_table[(unsigned) R_XTENSA_PDIFF16 ];
++
++    case BFD_RELOC_XTENSA_PDIFF32:
++      TRACE ("BFD_RELOC_XTENSA_PDIFF32");
++      return &elf_howto_table[(unsigned) R_XTENSA_PDIFF32 ];
++
++    case BFD_RELOC_XTENSA_NDIFF8:
++      TRACE ("BFD_RELOC_XTENSA_NDIFF8");
++      return &elf_howto_table[(unsigned) R_XTENSA_NDIFF8 ];
++
++    case BFD_RELOC_XTENSA_NDIFF16:
++      TRACE ("BFD_RELOC_XTENSA_NDIFF16");
++      return &elf_howto_table[(unsigned) R_XTENSA_NDIFF16 ];
++
++    case BFD_RELOC_XTENSA_NDIFF32:
++      TRACE ("BFD_RELOC_XTENSA_NDIFF32");
++      return &elf_howto_table[(unsigned) R_XTENSA_NDIFF32 ];
++
+     case BFD_RELOC_XTENSA_RTLD:
+       TRACE ("BFD_RELOC_XTENSA_RTLD");
+       return &elf_howto_table[(unsigned) R_XTENSA_RTLD ];
+@@ -1851,6 +1889,12 @@ elf_xtensa_do_reloc (reloc_howto_type *howto,
+     case R_XTENSA_DIFF8:
+     case R_XTENSA_DIFF16:
+     case R_XTENSA_DIFF32:
++    case R_XTENSA_PDIFF8:
++    case R_XTENSA_PDIFF16:
++    case R_XTENSA_PDIFF32:
++    case R_XTENSA_NDIFF8:
++    case R_XTENSA_NDIFF16:
++    case R_XTENSA_NDIFF32:
+     case R_XTENSA_TLS_FUNC:
+     case R_XTENSA_TLS_ARG:
+     case R_XTENSA_TLS_CALL:
+@@ -9604,7 +9648,13 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
+ 
+ 	      if (r_type == R_XTENSA_DIFF8
+ 		  || r_type == R_XTENSA_DIFF16
+-		  || r_type == R_XTENSA_DIFF32)
++		  || r_type == R_XTENSA_DIFF32
++		  || r_type == R_XTENSA_PDIFF8
++		  || r_type == R_XTENSA_PDIFF16
++		  || r_type == R_XTENSA_PDIFF32
++		  || r_type == R_XTENSA_NDIFF8
++		  || r_type == R_XTENSA_NDIFF16
++		  || r_type == R_XTENSA_NDIFF32)
+ 		{
+ 		  bfd_signed_vma diff_value = 0;
+ 		  bfd_vma new_end_offset, diff_mask = 0;
+@@ -9631,8 +9681,27 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
+ 		      diff_value =
+ 			bfd_get_signed_32 (abfd, &contents[old_source_offset]);
+ 		      break;
++		    case R_XTENSA_PDIFF8:
++		    case R_XTENSA_NDIFF8:
++		      diff_value =
++			bfd_get_8 (abfd, &contents[old_source_offset]);
++		      break;
++		    case R_XTENSA_PDIFF16:
++		    case R_XTENSA_NDIFF16:
++		      diff_value =
++			bfd_get_16 (abfd, &contents[old_source_offset]);
++		      break;
++		    case R_XTENSA_PDIFF32:
++		    case R_XTENSA_NDIFF32:
++		      diff_value =
++			bfd_get_32 (abfd, &contents[old_source_offset]);
++		      break;
+ 		    }
+ 
++		  if (r_type >= R_XTENSA_NDIFF8
++		      && r_type <= R_XTENSA_NDIFF32)
++		    diff_value = -diff_value;
++
+ 		  new_end_offset = offset_with_removed_text_map
+ 		    (&target_relax_info->action_list,
+ 		     r_rel.target_offset + diff_value);
+@@ -9655,6 +9724,24 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
+ 		      bfd_put_signed_32 (abfd, diff_value,
+ 				  &contents[old_source_offset]);
+ 		      break;
++		    case R_XTENSA_PDIFF8:
++		    case R_XTENSA_NDIFF8:
++		      diff_mask = 0xff;
++		      bfd_put_8 (abfd, diff_value,
++				 &contents[old_source_offset]);
++		      break;
++		    case R_XTENSA_PDIFF16:
++		    case R_XTENSA_NDIFF16:
++		      diff_mask = 0xffff;
++		      bfd_put_16 (abfd, diff_value,
++				  &contents[old_source_offset]);
++		      break;
++		    case R_XTENSA_PDIFF32:
++		    case R_XTENSA_NDIFF32:
++		      diff_mask = 0xffffffff;
++		      bfd_put_32 (abfd, diff_value,
++				  &contents[old_source_offset]);
++		      break;
+ 		    }
+ 
+ 		  /* Check for overflow. Sign bits must be all zeroes or all ones */
+diff --git a/bfd/libbfd.h b/bfd/libbfd.h
+index 3c184fcadadf..989f4bc0b595 100644
+--- a/bfd/libbfd.h
++++ b/bfd/libbfd.h
+@@ -2919,6 +2919,12 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
+   "BFD_RELOC_XTENSA_TLS_FUNC",
+   "BFD_RELOC_XTENSA_TLS_ARG",
+   "BFD_RELOC_XTENSA_TLS_CALL",
++  "BFD_RELOC_XTENSA_PDIFF8",
++  "BFD_RELOC_XTENSA_PDIFF16",
++  "BFD_RELOC_XTENSA_PDIFF32",
++  "BFD_RELOC_XTENSA_NDIFF8",
++  "BFD_RELOC_XTENSA_NDIFF16",
++  "BFD_RELOC_XTENSA_NDIFF32",
+   "BFD_RELOC_Z80_DISP8",
+   "BFD_RELOC_Z80_BYTE0",
+   "BFD_RELOC_Z80_BYTE1",
+diff --git a/bfd/reloc.c b/bfd/reloc.c
+index c4dec86d1d46..f5df8e2ab3eb 100644
+--- a/bfd/reloc.c
++++ b/bfd/reloc.c
+@@ -6556,6 +6556,8 @@ ENUMX
+ ENUMX
+   BFD_RELOC_XTENSA_DIFF32
+ ENUMDOC
++  Xtensa relocations for backward compatibility.  These have been replaced
++  by BFD_RELOC_XTENSA_PDIFF and BFD_RELOC_XTENSA_NDIFF.
+   Xtensa relocations to mark the difference of two local symbols.
+   These are only needed to support linker relaxation and can be ignored
+   when not relaxing.  The field is set to the value of the difference
+@@ -6668,6 +6670,28 @@ ENUMX
+   BFD_RELOC_XTENSA_TLS_CALL
+ ENUMDOC
+   Xtensa TLS relocations.
++ENUM
++  BFD_RELOC_XTENSA_PDIFF8
++ENUMX
++  BFD_RELOC_XTENSA_PDIFF16
++ENUMX
++  BFD_RELOC_XTENSA_PDIFF32
++ENUMX
++  BFD_RELOC_XTENSA_NDIFF8
++ENUMX
++  BFD_RELOC_XTENSA_NDIFF16
++ENUMX
++  BFD_RELOC_XTENSA_NDIFF32
++ENUMDOC
++  Xtensa relocations to mark the difference of two local symbols.
++  These are only needed to support linker relaxation and can be ignored
++  when not relaxing.  The field is set to the value of the difference
++  assuming no relaxation.  The relocation encodes the position of the
++  subtracted symbol so the linker can determine whether to adjust the field
++  value.  PDIFF relocations are used for positive differences, NDIFF
++  relocations are used for negative differences.  The difference value
++  is treated as unsigned with these relocation types, giving full
++  8/16 value ranges.
+ 
+ ENUM
+   BFD_RELOC_Z80_DISP8
+diff --git a/binutils/readelf.c b/binutils/readelf.c
+index d4756c93b345..800918f901c8 100644
+--- a/binutils/readelf.c
++++ b/binutils/readelf.c
+@@ -13262,7 +13262,13 @@ is_none_reloc (Filedata * filedata, unsigned int reloc_type)
+       return (reloc_type == 0      /* R_XTENSA_NONE.  */
+ 	      || reloc_type == 17  /* R_XTENSA_DIFF8.  */
+ 	      || reloc_type == 18  /* R_XTENSA_DIFF16.  */
+-	      || reloc_type == 19  /* R_XTENSA_DIFF32.  */);
++	      || reloc_type == 19  /* R_XTENSA_DIFF32.  */
++	      || reloc_type == 57  /* R_XTENSA_PDIFF8.  */
++	      || reloc_type == 58  /* R_XTENSA_PDIFF16.  */
++	      || reloc_type == 59  /* R_XTENSA_PDIFF32.  */
++	      || reloc_type == 60  /* R_XTENSA_NDIFF8.  */
++	      || reloc_type == 61  /* R_XTENSA_NDIFF16.  */
++	      || reloc_type == 62  /* R_XTENSA_NDIFF32.  */);
+     }
+   return FALSE;
+ }
+diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
+index 71d4d94a8d7d..ee75c13548ff 100644
+--- a/gas/config/tc-xtensa.c
++++ b/gas/config/tc-xtensa.c
+@@ -5974,18 +5974,24 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
+     case BFD_RELOC_8:
+       if (fixP->fx_subsy)
+ 	{
++	  bfd_boolean neg = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
++	    < S_GET_VALUE (fixP->fx_subsy);
++
+ 	  switch (fixP->fx_r_type)
+ 	    {
+ 	    case BFD_RELOC_8:
+-	      fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF8;
++	      fixP->fx_r_type = neg
++		? BFD_RELOC_XTENSA_NDIFF8 : BFD_RELOC_XTENSA_PDIFF8;
+ 	      fixP->fx_signed = 0;
+ 	      break;
+ 	    case BFD_RELOC_16:
+-	      fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF16;
++	      fixP->fx_r_type = neg
++		? BFD_RELOC_XTENSA_NDIFF16 : BFD_RELOC_XTENSA_PDIFF16;
+ 	      fixP->fx_signed = 0;
+ 	      break;
+ 	    case BFD_RELOC_32:
+-	      fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF32;
++	      fixP->fx_r_type = neg
++		? BFD_RELOC_XTENSA_NDIFF32 : BFD_RELOC_XTENSA_PDIFF32;
+ 	      fixP->fx_signed = 0;
+ 	      break;
+ 	    default:
+diff --git a/gas/testsuite/gas/xtensa/loc.d b/gas/testsuite/gas/xtensa/loc.d
+index 71983cc90055..8fb3425999d5 100644
+--- a/gas/testsuite/gas/xtensa/loc.d
++++ b/gas/testsuite/gas/xtensa/loc.d
+@@ -6,5 +6,5 @@
+ 
+ RELOCATION RECORDS FOR \[\.debug_line\]:
+ #...
+-.*R_XTENSA_DIFF16.*\.text\+0x00009c42
++.*R_XTENSA_PDIFF16.*\.text\+0x00009c42
+ #...
+diff --git a/include/elf/xtensa.h b/include/elf/xtensa.h
+index 2eb5e4e52941..bd5c80d13777 100644
+--- a/include/elf/xtensa.h
++++ b/include/elf/xtensa.h
+@@ -87,6 +87,12 @@ START_RELOC_NUMBERS (elf_xtensa_reloc_type)
+      RELOC_NUMBER (R_XTENSA_TLS_FUNC, 54)
+      RELOC_NUMBER (R_XTENSA_TLS_ARG, 55)
+      RELOC_NUMBER (R_XTENSA_TLS_CALL, 56)
++     RELOC_NUMBER (R_XTENSA_PDIFF8, 57)
++     RELOC_NUMBER (R_XTENSA_PDIFF16, 58)
++     RELOC_NUMBER (R_XTENSA_PDIFF32, 59)
++     RELOC_NUMBER (R_XTENSA_NDIFF8, 60)
++     RELOC_NUMBER (R_XTENSA_NDIFF16, 61)
++     RELOC_NUMBER (R_XTENSA_NDIFF32, 62)
+ END_RELOC_NUMBERS (R_XTENSA_max)
+ 
+ /* Processor-specific flags for the ELF header e_flags field.  */
+-- 
+2.20.1
+
diff --git a/package/binutils/2.32/0008-xtensa-fix-PR-ld-25861.patch b/package/binutils/2.32/0008-xtensa-fix-PR-ld-25861.patch
new file mode 100644
index 0000000000..2df46c6526
--- /dev/null
+++ b/package/binutils/2.32/0008-xtensa-fix-PR-ld-25861.patch
@@ -0,0 +1,432 @@
+From c7a1d1f656c717394937a92cb970f0f4cecce128 Mon Sep 17 00:00:00 2001
+From: Max Filippov <jcmvbkbc@gmail.com>
+Date: Sun, 19 Apr 2020 19:04:41 -0700
+Subject: [PATCH] xtensa: fix PR ld/25861
+
+Introduce new relaxations XTENSA_PDIFF{8,16,32} for positive differences
+(subtracted symbol precedes diminished symbol) and XTENSA_NDIFF{8,16,32}
+for negative differences (subtracted symbol follows diminished symbol).
+Don't generate XTENSA_DIFF relocations in the assembler, generate
+XTENSA_PDIFF or XTENSA_NDIFF based on relative symbol position.
+
+Handle XTENSA_DIFF in BFD for compatibility with old object files.
+Handle XTENSA_PDIFF and XTENSA_NDIFF in BFD, treating difference value
+as unsigned.
+
+2020-04-22  Max Filippov  <jcmvbkbc@gmail.com>
+bfd/
+	* bfd-in2.h: Regenerated.
+	* elf32-xtensa.c (elf_howto_table): New entries for
+	R_XTENSA_PDIFF{8,16,32} and R_XTENSA_NDIFF{8,16,32}.
+	(elf_xtensa_reloc_type_lookup, elf_xtensa_do_reloc)
+	(relax_section): Add cases for R_XTENSA_PDIFF{8,16,32} and
+	R_XTENSA_NDIFF{8,16,32}.
+	* libbfd.h (bfd_reloc_code_real_names): Add names for
+	BFD_RELOC_XTENSA_PDIFF{8,16,32} and
+	BFD_RELOC_XTENSA_NDIFF{8,16,32}.
+	* reloc.c: Add documentation for BFD_RELOC_XTENSA_PDIFF{8,16,32}
+	and BFD_RELOC_XTENSA_NDIFF{8,16,32}.
+
+binutils/
+	* readelf.c (is_none_reloc): Recognize
+	BFD_RELOC_XTENSA_PDIFF{8,16,32} and
+	BFD_RELOC_XTENSA_NDIFF{8,16,32}.
+
+gas/
+	* config/tc-xtensa.c (md_apply_fix): Replace
+	BFD_RELOC_XTENSA_DIFF{8,16,32} generation with
+	BFD_RELOC_XTENSA_PDIFF{8,16,32} and
+	BFD_RELOC_XTENSA_NDIFF{8,16,32} generation.
+	* testsuite/gas/xtensa/loc.d: Replace BFD_RELOC_XTENSA_DIFF16
+	with BFD_RELOC_XTENSA_PDIFF16 in the expected output.
+
+include/
+	* elf/xtensa.h (elf_xtensa_reloc_type): New entries for
+	R_XTENSA_PDIFF{8,16,32} and R_XTENSA_NDIFF{8,16,32}.
+
+ld/
+	* testsuite/ld-xtensa/relax-loc.d: New test definition.
+	* testsuite/ld-xtensa/relax-loc.s: New test source.
+	* testsuite/ld-xtensa/xtensa.exp (relax-loc): New test.
+
+Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
+---
+Backported from: 30ce8e47fad9b057b6d7af9e1d43061126d34d20
+
+ bfd/bfd-in2.h                      | 20 ++++++-
+ bfd/elf32-xtensa.c                 | 89 +++++++++++++++++++++++++++++-
+ bfd/libbfd.h                       |  6 ++
+ bfd/reloc.c                        | 24 ++++++++
+ binutils/readelf.c                 |  8 ++-
+ gas/config/tc-xtensa.c             | 12 +++-
+ gas/testsuite/gas/xtensa/loc.d     |  2 +-
+ include/elf/xtensa.h               |  6 ++
+ ld/testsuite/ld-xtensa/relax-loc.d |  7 +++
+ ld/testsuite/ld-xtensa/relax-loc.s | 15 +++++
+ ld/testsuite/ld-xtensa/xtensa.exp  |  1 +
+ 11 files changed, 183 insertions(+), 7 deletions(-)
+ create mode 100644 ld/testsuite/ld-xtensa/relax-loc.d
+ create mode 100644 ld/testsuite/ld-xtensa/relax-loc.s
+
+diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
+index 37114607b515..be6a30f57955 100644
+--- a/bfd/bfd-in2.h
++++ b/bfd/bfd-in2.h
+@@ -5217,7 +5217,9 @@ to one of its own internal functions or data structures.  */
+ PLT entries.  Otherwise, this is just a generic 32-bit relocation.  */
+   BFD_RELOC_XTENSA_PLT,
+ 
+-/* Xtensa relocations to mark the difference of two local symbols.
++/* Xtensa relocations for backward compatibility.  These have been replaced
++by BFD_RELOC_XTENSA_PDIFF and BFD_RELOC_XTENSA_NDIFF.
++Xtensa relocations to mark the difference of two local symbols.
+ These are only needed to support linker relaxation and can be ignored
+ when not relaxing.  The field is set to the value of the difference
+ assuming no relaxation.  The relocation encodes the position of the
+@@ -5291,6 +5293,22 @@ BFD_RELOC_XTENSA_ASM_EXPAND.  */
+   BFD_RELOC_XTENSA_TLS_ARG,
+   BFD_RELOC_XTENSA_TLS_CALL,
+ 
++/* Xtensa relocations to mark the difference of two local symbols.
++These are only needed to support linker relaxation and can be ignored
++when not relaxing.  The field is set to the value of the difference
++assuming no relaxation.  The relocation encodes the position of the
++subtracted symbol so the linker can determine whether to adjust the field
++value.  PDIFF relocations are used for positive differences, NDIFF
++relocations are used for negative differences.  The difference value
++is treated as unsigned with these relocation types, giving full
++8/16 value ranges.  */
++  BFD_RELOC_XTENSA_PDIFF8,
++  BFD_RELOC_XTENSA_PDIFF16,
++  BFD_RELOC_XTENSA_PDIFF32,
++  BFD_RELOC_XTENSA_NDIFF8,
++  BFD_RELOC_XTENSA_NDIFF16,
++  BFD_RELOC_XTENSA_NDIFF32,
++
+ /* 8 bit signed offset in (ix+d) or (iy+d).  */
+   BFD_RELOC_Z80_DISP8,
+ 
+diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
+index 473a9d76f289..fded42d52a9a 100644
+--- a/bfd/elf32-xtensa.c
++++ b/bfd/elf32-xtensa.c
+@@ -325,6 +325,20 @@ static reloc_howto_type elf_howto_table[] =
+   HOWTO (R_XTENSA_TLS_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+ 	 bfd_elf_xtensa_reloc, "R_XTENSA_TLS_CALL",
+ 	 FALSE, 0, 0, FALSE),
++
++  HOWTO (R_XTENSA_PDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF8", FALSE, 0, 0xff, FALSE),
++  HOWTO (R_XTENSA_PDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF16", FALSE, 0, 0xffff, FALSE),
++  HOWTO (R_XTENSA_PDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF32", FALSE, 0, 0xffffffff, FALSE),
++
++  HOWTO (R_XTENSA_NDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF8", FALSE, 0, 0xff, FALSE),
++  HOWTO (R_XTENSA_NDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF16", FALSE, 0, 0xffff, FALSE),
++  HOWTO (R_XTENSA_NDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF32", FALSE, 0, 0xffffffff, FALSE),
+ };
+ 
+ #if DEBUG_GEN_RELOC
+@@ -364,6 +378,30 @@ elf_xtensa_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+       TRACE ("BFD_RELOC_XTENSA_DIFF32");
+       return &elf_howto_table[(unsigned) R_XTENSA_DIFF32 ];
+ 
++    case BFD_RELOC_XTENSA_PDIFF8:
++      TRACE ("BFD_RELOC_XTENSA_PDIFF8");
++      return &elf_howto_table[(unsigned) R_XTENSA_PDIFF8 ];
++
++    case BFD_RELOC_XTENSA_PDIFF16:
++      TRACE ("BFD_RELOC_XTENSA_PDIFF16");
++      return &elf_howto_table[(unsigned) R_XTENSA_PDIFF16 ];
++
++    case BFD_RELOC_XTENSA_PDIFF32:
++      TRACE ("BFD_RELOC_XTENSA_PDIFF32");
++      return &elf_howto_table[(unsigned) R_XTENSA_PDIFF32 ];
++
++    case BFD_RELOC_XTENSA_NDIFF8:
++      TRACE ("BFD_RELOC_XTENSA_NDIFF8");
++      return &elf_howto_table[(unsigned) R_XTENSA_NDIFF8 ];
++
++    case BFD_RELOC_XTENSA_NDIFF16:
++      TRACE ("BFD_RELOC_XTENSA_NDIFF16");
++      return &elf_howto_table[(unsigned) R_XTENSA_NDIFF16 ];
++
++    case BFD_RELOC_XTENSA_NDIFF32:
++      TRACE ("BFD_RELOC_XTENSA_NDIFF32");
++      return &elf_howto_table[(unsigned) R_XTENSA_NDIFF32 ];
++
+     case BFD_RELOC_XTENSA_RTLD:
+       TRACE ("BFD_RELOC_XTENSA_RTLD");
+       return &elf_howto_table[(unsigned) R_XTENSA_RTLD ];
+@@ -1851,6 +1889,12 @@ elf_xtensa_do_reloc (reloc_howto_type *howto,
+     case R_XTENSA_DIFF8:
+     case R_XTENSA_DIFF16:
+     case R_XTENSA_DIFF32:
++    case R_XTENSA_PDIFF8:
++    case R_XTENSA_PDIFF16:
++    case R_XTENSA_PDIFF32:
++    case R_XTENSA_NDIFF8:
++    case R_XTENSA_NDIFF16:
++    case R_XTENSA_NDIFF32:
+     case R_XTENSA_TLS_FUNC:
+     case R_XTENSA_TLS_ARG:
+     case R_XTENSA_TLS_CALL:
+@@ -9604,7 +9648,13 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
+ 
+ 	      if (r_type == R_XTENSA_DIFF8
+ 		  || r_type == R_XTENSA_DIFF16
+-		  || r_type == R_XTENSA_DIFF32)
++		  || r_type == R_XTENSA_DIFF32
++		  || r_type == R_XTENSA_PDIFF8
++		  || r_type == R_XTENSA_PDIFF16
++		  || r_type == R_XTENSA_PDIFF32
++		  || r_type == R_XTENSA_NDIFF8
++		  || r_type == R_XTENSA_NDIFF16
++		  || r_type == R_XTENSA_NDIFF32)
+ 		{
+ 		  bfd_signed_vma diff_value = 0;
+ 		  bfd_vma new_end_offset, diff_mask = 0;
+@@ -9631,8 +9681,27 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
+ 		      diff_value =
+ 			bfd_get_signed_32 (abfd, &contents[old_source_offset]);
+ 		      break;
++		    case R_XTENSA_PDIFF8:
++		    case R_XTENSA_NDIFF8:
++		      diff_value =
++			bfd_get_8 (abfd, &contents[old_source_offset]);
++		      break;
++		    case R_XTENSA_PDIFF16:
++		    case R_XTENSA_NDIFF16:
++		      diff_value =
++			bfd_get_16 (abfd, &contents[old_source_offset]);
++		      break;
++		    case R_XTENSA_PDIFF32:
++		    case R_XTENSA_NDIFF32:
++		      diff_value =
++			bfd_get_32 (abfd, &contents[old_source_offset]);
++		      break;
+ 		    }
+ 
++		  if (r_type >= R_XTENSA_NDIFF8
++		      && r_type <= R_XTENSA_NDIFF32)
++		    diff_value = -diff_value;
++
+ 		  new_end_offset = offset_with_removed_text_map
+ 		    (&target_relax_info->action_list,
+ 		     r_rel.target_offset + diff_value);
+@@ -9655,6 +9724,24 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
+ 		      bfd_put_signed_32 (abfd, diff_value,
+ 				  &contents[old_source_offset]);
+ 		      break;
++		    case R_XTENSA_PDIFF8:
++		    case R_XTENSA_NDIFF8:
++		      diff_mask = 0xff;
++		      bfd_put_8 (abfd, diff_value,
++				 &contents[old_source_offset]);
++		      break;
++		    case R_XTENSA_PDIFF16:
++		    case R_XTENSA_NDIFF16:
++		      diff_mask = 0xffff;
++		      bfd_put_16 (abfd, diff_value,
++				  &contents[old_source_offset]);
++		      break;
++		    case R_XTENSA_PDIFF32:
++		    case R_XTENSA_NDIFF32:
++		      diff_mask = 0xffffffff;
++		      bfd_put_32 (abfd, diff_value,
++				  &contents[old_source_offset]);
++		      break;
+ 		    }
+ 
+ 		  /* Check for overflow. Sign bits must be all zeroes or all ones */
+diff --git a/bfd/libbfd.h b/bfd/libbfd.h
+index 3c184fcadadf..989f4bc0b595 100644
+--- a/bfd/libbfd.h
++++ b/bfd/libbfd.h
+@@ -2919,6 +2919,12 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
+   "BFD_RELOC_XTENSA_TLS_FUNC",
+   "BFD_RELOC_XTENSA_TLS_ARG",
+   "BFD_RELOC_XTENSA_TLS_CALL",
++  "BFD_RELOC_XTENSA_PDIFF8",
++  "BFD_RELOC_XTENSA_PDIFF16",
++  "BFD_RELOC_XTENSA_PDIFF32",
++  "BFD_RELOC_XTENSA_NDIFF8",
++  "BFD_RELOC_XTENSA_NDIFF16",
++  "BFD_RELOC_XTENSA_NDIFF32",
+   "BFD_RELOC_Z80_DISP8",
+   "BFD_RELOC_Z80_BYTE0",
+   "BFD_RELOC_Z80_BYTE1",
+diff --git a/bfd/reloc.c b/bfd/reloc.c
+index c4dec86d1d46..f5df8e2ab3eb 100644
+--- a/bfd/reloc.c
++++ b/bfd/reloc.c
+@@ -6556,6 +6556,8 @@ ENUMX
+ ENUMX
+   BFD_RELOC_XTENSA_DIFF32
+ ENUMDOC
++  Xtensa relocations for backward compatibility.  These have been replaced
++  by BFD_RELOC_XTENSA_PDIFF and BFD_RELOC_XTENSA_NDIFF.
+   Xtensa relocations to mark the difference of two local symbols.
+   These are only needed to support linker relaxation and can be ignored
+   when not relaxing.  The field is set to the value of the difference
+@@ -6668,6 +6670,28 @@ ENUMX
+   BFD_RELOC_XTENSA_TLS_CALL
+ ENUMDOC
+   Xtensa TLS relocations.
++ENUM
++  BFD_RELOC_XTENSA_PDIFF8
++ENUMX
++  BFD_RELOC_XTENSA_PDIFF16
++ENUMX
++  BFD_RELOC_XTENSA_PDIFF32
++ENUMX
++  BFD_RELOC_XTENSA_NDIFF8
++ENUMX
++  BFD_RELOC_XTENSA_NDIFF16
++ENUMX
++  BFD_RELOC_XTENSA_NDIFF32
++ENUMDOC
++  Xtensa relocations to mark the difference of two local symbols.
++  These are only needed to support linker relaxation and can be ignored
++  when not relaxing.  The field is set to the value of the difference
++  assuming no relaxation.  The relocation encodes the position of the
++  subtracted symbol so the linker can determine whether to adjust the field
++  value.  PDIFF relocations are used for positive differences, NDIFF
++  relocations are used for negative differences.  The difference value
++  is treated as unsigned with these relocation types, giving full
++  8/16 value ranges.
+ 
+ ENUM
+   BFD_RELOC_Z80_DISP8
+diff --git a/binutils/readelf.c b/binutils/readelf.c
+index d4756c93b345..800918f901c8 100644
+--- a/binutils/readelf.c
++++ b/binutils/readelf.c
+@@ -13262,7 +13262,13 @@ is_none_reloc (Filedata * filedata, unsigned int reloc_type)
+       return (reloc_type == 0      /* R_XTENSA_NONE.  */
+ 	      || reloc_type == 17  /* R_XTENSA_DIFF8.  */
+ 	      || reloc_type == 18  /* R_XTENSA_DIFF16.  */
+-	      || reloc_type == 19  /* R_XTENSA_DIFF32.  */);
++	      || reloc_type == 19  /* R_XTENSA_DIFF32.  */
++	      || reloc_type == 57  /* R_XTENSA_PDIFF8.  */
++	      || reloc_type == 58  /* R_XTENSA_PDIFF16.  */
++	      || reloc_type == 59  /* R_XTENSA_PDIFF32.  */
++	      || reloc_type == 60  /* R_XTENSA_NDIFF8.  */
++	      || reloc_type == 61  /* R_XTENSA_NDIFF16.  */
++	      || reloc_type == 62  /* R_XTENSA_NDIFF32.  */);
+     }
+   return FALSE;
+ }
+diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
+index 71d4d94a8d7d..ee75c13548ff 100644
+--- a/gas/config/tc-xtensa.c
++++ b/gas/config/tc-xtensa.c
+@@ -5974,18 +5974,24 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
+     case BFD_RELOC_8:
+       if (fixP->fx_subsy)
+ 	{
++	  bfd_boolean neg = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
++	    < S_GET_VALUE (fixP->fx_subsy);
++
+ 	  switch (fixP->fx_r_type)
+ 	    {
+ 	    case BFD_RELOC_8:
+-	      fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF8;
++	      fixP->fx_r_type = neg
++		? BFD_RELOC_XTENSA_NDIFF8 : BFD_RELOC_XTENSA_PDIFF8;
+ 	      fixP->fx_signed = 0;
+ 	      break;
+ 	    case BFD_RELOC_16:
+-	      fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF16;
++	      fixP->fx_r_type = neg
++		? BFD_RELOC_XTENSA_NDIFF16 : BFD_RELOC_XTENSA_PDIFF16;
+ 	      fixP->fx_signed = 0;
+ 	      break;
+ 	    case BFD_RELOC_32:
+-	      fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF32;
++	      fixP->fx_r_type = neg
++		? BFD_RELOC_XTENSA_NDIFF32 : BFD_RELOC_XTENSA_PDIFF32;
+ 	      fixP->fx_signed = 0;
+ 	      break;
+ 	    default:
+diff --git a/gas/testsuite/gas/xtensa/loc.d b/gas/testsuite/gas/xtensa/loc.d
+index 71983cc90055..8fb3425999d5 100644
+--- a/gas/testsuite/gas/xtensa/loc.d
++++ b/gas/testsuite/gas/xtensa/loc.d
+@@ -6,5 +6,5 @@
+ 
+ RELOCATION RECORDS FOR \[\.debug_line\]:
+ #...
+-.*R_XTENSA_DIFF16.*\.text\+0x00009c42
++.*R_XTENSA_PDIFF16.*\.text\+0x00009c42
+ #...
+diff --git a/include/elf/xtensa.h b/include/elf/xtensa.h
+index 2eb5e4e52941..bd5c80d13777 100644
+--- a/include/elf/xtensa.h
++++ b/include/elf/xtensa.h
+@@ -87,6 +87,12 @@ START_RELOC_NUMBERS (elf_xtensa_reloc_type)
+      RELOC_NUMBER (R_XTENSA_TLS_FUNC, 54)
+      RELOC_NUMBER (R_XTENSA_TLS_ARG, 55)
+      RELOC_NUMBER (R_XTENSA_TLS_CALL, 56)
++     RELOC_NUMBER (R_XTENSA_PDIFF8, 57)
++     RELOC_NUMBER (R_XTENSA_PDIFF16, 58)
++     RELOC_NUMBER (R_XTENSA_PDIFF32, 59)
++     RELOC_NUMBER (R_XTENSA_NDIFF8, 60)
++     RELOC_NUMBER (R_XTENSA_NDIFF16, 61)
++     RELOC_NUMBER (R_XTENSA_NDIFF32, 62)
+ END_RELOC_NUMBERS (R_XTENSA_max)
+ 
+ /* Processor-specific flags for the ELF header e_flags field.  */
+diff --git a/ld/testsuite/ld-xtensa/relax-loc.d b/ld/testsuite/ld-xtensa/relax-loc.d
+new file mode 100644
+index 000000000000..3c8d673732ff
+--- /dev/null
++++ b/ld/testsuite/ld-xtensa/relax-loc.d
+@@ -0,0 +1,7 @@
++#as: --text-section-literals
++#ld:
++#objdump: --dwarf=decodedline
++#...
++relax-loc.s[ 	]+1[ 	]+0x400054[ 	]+.*
++relax-loc.s[ 	]+2[ 	]+0x40005c[ 	]+.*
++#...
+diff --git a/ld/testsuite/ld-xtensa/relax-loc.s b/ld/testsuite/ld-xtensa/relax-loc.s
+new file mode 100644
+index 000000000000..d768470e287a
+--- /dev/null
++++ b/ld/testsuite/ld-xtensa/relax-loc.s
+@@ -0,0 +1,15 @@
++	.file	1 "relax-loc.s"
++	.globl	_start
++	.globl	_ResetVector
++	.text
++_ResetVector:
++_start:
++	.loc	1 1
++	j	1f
++	.literal_position
++1:
++	.loc	1 2
++
++	.rep	10000
++	movi	a2, 0x12345678
++	.endr
+diff --git a/ld/testsuite/ld-xtensa/xtensa.exp b/ld/testsuite/ld-xtensa/xtensa.exp
+index 9b2235b2151b..de39887936ad 100644
+--- a/ld/testsuite/ld-xtensa/xtensa.exp
++++ b/ld/testsuite/ld-xtensa/xtensa.exp
+@@ -27,6 +27,7 @@ run_dump_test "call_overflow"
+ run_dump_test "coalesce"
+ run_dump_test "diff_overflow"
+ run_dump_test "lcall"
++run_dump_test "relax-loc"
+ 
+ run_dump_test "relax-static-pie"
+ run_dump_test "relax-static-local-pie"
+-- 
+2.20.1
+
diff --git a/package/binutils/2.33.1/0005-xtensa-fix-PR-ld-25861.patch b/package/binutils/2.33.1/0005-xtensa-fix-PR-ld-25861.patch
new file mode 100644
index 0000000000..2df46c6526
--- /dev/null
+++ b/package/binutils/2.33.1/0005-xtensa-fix-PR-ld-25861.patch
@@ -0,0 +1,432 @@
+From c7a1d1f656c717394937a92cb970f0f4cecce128 Mon Sep 17 00:00:00 2001
+From: Max Filippov <jcmvbkbc@gmail.com>
+Date: Sun, 19 Apr 2020 19:04:41 -0700
+Subject: [PATCH] xtensa: fix PR ld/25861
+
+Introduce new relaxations XTENSA_PDIFF{8,16,32} for positive differences
+(subtracted symbol precedes diminished symbol) and XTENSA_NDIFF{8,16,32}
+for negative differences (subtracted symbol follows diminished symbol).
+Don't generate XTENSA_DIFF relocations in the assembler, generate
+XTENSA_PDIFF or XTENSA_NDIFF based on relative symbol position.
+
+Handle XTENSA_DIFF in BFD for compatibility with old object files.
+Handle XTENSA_PDIFF and XTENSA_NDIFF in BFD, treating difference value
+as unsigned.
+
+2020-04-22  Max Filippov  <jcmvbkbc@gmail.com>
+bfd/
+	* bfd-in2.h: Regenerated.
+	* elf32-xtensa.c (elf_howto_table): New entries for
+	R_XTENSA_PDIFF{8,16,32} and R_XTENSA_NDIFF{8,16,32}.
+	(elf_xtensa_reloc_type_lookup, elf_xtensa_do_reloc)
+	(relax_section): Add cases for R_XTENSA_PDIFF{8,16,32} and
+	R_XTENSA_NDIFF{8,16,32}.
+	* libbfd.h (bfd_reloc_code_real_names): Add names for
+	BFD_RELOC_XTENSA_PDIFF{8,16,32} and
+	BFD_RELOC_XTENSA_NDIFF{8,16,32}.
+	* reloc.c: Add documentation for BFD_RELOC_XTENSA_PDIFF{8,16,32}
+	and BFD_RELOC_XTENSA_NDIFF{8,16,32}.
+
+binutils/
+	* readelf.c (is_none_reloc): Recognize
+	BFD_RELOC_XTENSA_PDIFF{8,16,32} and
+	BFD_RELOC_XTENSA_NDIFF{8,16,32}.
+
+gas/
+	* config/tc-xtensa.c (md_apply_fix): Replace
+	BFD_RELOC_XTENSA_DIFF{8,16,32} generation with
+	BFD_RELOC_XTENSA_PDIFF{8,16,32} and
+	BFD_RELOC_XTENSA_NDIFF{8,16,32} generation.
+	* testsuite/gas/xtensa/loc.d: Replace BFD_RELOC_XTENSA_DIFF16
+	with BFD_RELOC_XTENSA_PDIFF16 in the expected output.
+
+include/
+	* elf/xtensa.h (elf_xtensa_reloc_type): New entries for
+	R_XTENSA_PDIFF{8,16,32} and R_XTENSA_NDIFF{8,16,32}.
+
+ld/
+	* testsuite/ld-xtensa/relax-loc.d: New test definition.
+	* testsuite/ld-xtensa/relax-loc.s: New test source.
+	* testsuite/ld-xtensa/xtensa.exp (relax-loc): New test.
+
+Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
+---
+Backported from: 30ce8e47fad9b057b6d7af9e1d43061126d34d20
+
+ bfd/bfd-in2.h                      | 20 ++++++-
+ bfd/elf32-xtensa.c                 | 89 +++++++++++++++++++++++++++++-
+ bfd/libbfd.h                       |  6 ++
+ bfd/reloc.c                        | 24 ++++++++
+ binutils/readelf.c                 |  8 ++-
+ gas/config/tc-xtensa.c             | 12 +++-
+ gas/testsuite/gas/xtensa/loc.d     |  2 +-
+ include/elf/xtensa.h               |  6 ++
+ ld/testsuite/ld-xtensa/relax-loc.d |  7 +++
+ ld/testsuite/ld-xtensa/relax-loc.s | 15 +++++
+ ld/testsuite/ld-xtensa/xtensa.exp  |  1 +
+ 11 files changed, 183 insertions(+), 7 deletions(-)
+ create mode 100644 ld/testsuite/ld-xtensa/relax-loc.d
+ create mode 100644 ld/testsuite/ld-xtensa/relax-loc.s
+
+diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
+index 37114607b515..be6a30f57955 100644
+--- a/bfd/bfd-in2.h
++++ b/bfd/bfd-in2.h
+@@ -5217,7 +5217,9 @@ to one of its own internal functions or data structures.  */
+ PLT entries.  Otherwise, this is just a generic 32-bit relocation.  */
+   BFD_RELOC_XTENSA_PLT,
+ 
+-/* Xtensa relocations to mark the difference of two local symbols.
++/* Xtensa relocations for backward compatibility.  These have been replaced
++by BFD_RELOC_XTENSA_PDIFF and BFD_RELOC_XTENSA_NDIFF.
++Xtensa relocations to mark the difference of two local symbols.
+ These are only needed to support linker relaxation and can be ignored
+ when not relaxing.  The field is set to the value of the difference
+ assuming no relaxation.  The relocation encodes the position of the
+@@ -5291,6 +5293,22 @@ BFD_RELOC_XTENSA_ASM_EXPAND.  */
+   BFD_RELOC_XTENSA_TLS_ARG,
+   BFD_RELOC_XTENSA_TLS_CALL,
+ 
++/* Xtensa relocations to mark the difference of two local symbols.
++These are only needed to support linker relaxation and can be ignored
++when not relaxing.  The field is set to the value of the difference
++assuming no relaxation.  The relocation encodes the position of the
++subtracted symbol so the linker can determine whether to adjust the field
++value.  PDIFF relocations are used for positive differences, NDIFF
++relocations are used for negative differences.  The difference value
++is treated as unsigned with these relocation types, giving full
++8/16 value ranges.  */
++  BFD_RELOC_XTENSA_PDIFF8,
++  BFD_RELOC_XTENSA_PDIFF16,
++  BFD_RELOC_XTENSA_PDIFF32,
++  BFD_RELOC_XTENSA_NDIFF8,
++  BFD_RELOC_XTENSA_NDIFF16,
++  BFD_RELOC_XTENSA_NDIFF32,
++
+ /* 8 bit signed offset in (ix+d) or (iy+d).  */
+   BFD_RELOC_Z80_DISP8,
+ 
+diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
+index 473a9d76f289..fded42d52a9a 100644
+--- a/bfd/elf32-xtensa.c
++++ b/bfd/elf32-xtensa.c
+@@ -325,6 +325,20 @@ static reloc_howto_type elf_howto_table[] =
+   HOWTO (R_XTENSA_TLS_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+ 	 bfd_elf_xtensa_reloc, "R_XTENSA_TLS_CALL",
+ 	 FALSE, 0, 0, FALSE),
++
++  HOWTO (R_XTENSA_PDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF8", FALSE, 0, 0xff, FALSE),
++  HOWTO (R_XTENSA_PDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF16", FALSE, 0, 0xffff, FALSE),
++  HOWTO (R_XTENSA_PDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF32", FALSE, 0, 0xffffffff, FALSE),
++
++  HOWTO (R_XTENSA_NDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF8", FALSE, 0, 0xff, FALSE),
++  HOWTO (R_XTENSA_NDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF16", FALSE, 0, 0xffff, FALSE),
++  HOWTO (R_XTENSA_NDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
++	 bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF32", FALSE, 0, 0xffffffff, FALSE),
+ };
+ 
+ #if DEBUG_GEN_RELOC
+@@ -364,6 +378,30 @@ elf_xtensa_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+       TRACE ("BFD_RELOC_XTENSA_DIFF32");
+       return &elf_howto_table[(unsigned) R_XTENSA_DIFF32 ];
+ 
++    case BFD_RELOC_XTENSA_PDIFF8:
++      TRACE ("BFD_RELOC_XTENSA_PDIFF8");
++      return &elf_howto_table[(unsigned) R_XTENSA_PDIFF8 ];
++
++    case BFD_RELOC_XTENSA_PDIFF16:
++      TRACE ("BFD_RELOC_XTENSA_PDIFF16");
++      return &elf_howto_table[(unsigned) R_XTENSA_PDIFF16 ];
++
++    case BFD_RELOC_XTENSA_PDIFF32:
++      TRACE ("BFD_RELOC_XTENSA_PDIFF32");
++      return &elf_howto_table[(unsigned) R_XTENSA_PDIFF32 ];
++
++    case BFD_RELOC_XTENSA_NDIFF8:
++      TRACE ("BFD_RELOC_XTENSA_NDIFF8");
++      return &elf_howto_table[(unsigned) R_XTENSA_NDIFF8 ];
++
++    case BFD_RELOC_XTENSA_NDIFF16:
++      TRACE ("BFD_RELOC_XTENSA_NDIFF16");
++      return &elf_howto_table[(unsigned) R_XTENSA_NDIFF16 ];
++
++    case BFD_RELOC_XTENSA_NDIFF32:
++      TRACE ("BFD_RELOC_XTENSA_NDIFF32");
++      return &elf_howto_table[(unsigned) R_XTENSA_NDIFF32 ];
++
+     case BFD_RELOC_XTENSA_RTLD:
+       TRACE ("BFD_RELOC_XTENSA_RTLD");
+       return &elf_howto_table[(unsigned) R_XTENSA_RTLD ];
+@@ -1851,6 +1889,12 @@ elf_xtensa_do_reloc (reloc_howto_type *howto,
+     case R_XTENSA_DIFF8:
+     case R_XTENSA_DIFF16:
+     case R_XTENSA_DIFF32:
++    case R_XTENSA_PDIFF8:
++    case R_XTENSA_PDIFF16:
++    case R_XTENSA_PDIFF32:
++    case R_XTENSA_NDIFF8:
++    case R_XTENSA_NDIFF16:
++    case R_XTENSA_NDIFF32:
+     case R_XTENSA_TLS_FUNC:
+     case R_XTENSA_TLS_ARG:
+     case R_XTENSA_TLS_CALL:
+@@ -9604,7 +9648,13 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
+ 
+ 	      if (r_type == R_XTENSA_DIFF8
+ 		  || r_type == R_XTENSA_DIFF16
+-		  || r_type == R_XTENSA_DIFF32)
++		  || r_type == R_XTENSA_DIFF32
++		  || r_type == R_XTENSA_PDIFF8
++		  || r_type == R_XTENSA_PDIFF16
++		  || r_type == R_XTENSA_PDIFF32
++		  || r_type == R_XTENSA_NDIFF8
++		  || r_type == R_XTENSA_NDIFF16
++		  || r_type == R_XTENSA_NDIFF32)
+ 		{
+ 		  bfd_signed_vma diff_value = 0;
+ 		  bfd_vma new_end_offset, diff_mask = 0;
+@@ -9631,8 +9681,27 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
+ 		      diff_value =
+ 			bfd_get_signed_32 (abfd, &contents[old_source_offset]);
+ 		      break;
++		    case R_XTENSA_PDIFF8:
++		    case R_XTENSA_NDIFF8:
++		      diff_value =
++			bfd_get_8 (abfd, &contents[old_source_offset]);
++		      break;
++		    case R_XTENSA_PDIFF16:
++		    case R_XTENSA_NDIFF16:
++		      diff_value =
++			bfd_get_16 (abfd, &contents[old_source_offset]);
++		      break;
++		    case R_XTENSA_PDIFF32:
++		    case R_XTENSA_NDIFF32:
++		      diff_value =
++			bfd_get_32 (abfd, &contents[old_source_offset]);
++		      break;
+ 		    }
+ 
++		  if (r_type >= R_XTENSA_NDIFF8
++		      && r_type <= R_XTENSA_NDIFF32)
++		    diff_value = -diff_value;
++
+ 		  new_end_offset = offset_with_removed_text_map
+ 		    (&target_relax_info->action_list,
+ 		     r_rel.target_offset + diff_value);
+@@ -9655,6 +9724,24 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
+ 		      bfd_put_signed_32 (abfd, diff_value,
+ 				  &contents[old_source_offset]);
+ 		      break;
++		    case R_XTENSA_PDIFF8:
++		    case R_XTENSA_NDIFF8:
++		      diff_mask = 0xff;
++		      bfd_put_8 (abfd, diff_value,
++				 &contents[old_source_offset]);
++		      break;
++		    case R_XTENSA_PDIFF16:
++		    case R_XTENSA_NDIFF16:
++		      diff_mask = 0xffff;
++		      bfd_put_16 (abfd, diff_value,
++				  &contents[old_source_offset]);
++		      break;
++		    case R_XTENSA_PDIFF32:
++		    case R_XTENSA_NDIFF32:
++		      diff_mask = 0xffffffff;
++		      bfd_put_32 (abfd, diff_value,
++				  &contents[old_source_offset]);
++		      break;
+ 		    }
+ 
+ 		  /* Check for overflow. Sign bits must be all zeroes or all ones */
+diff --git a/bfd/libbfd.h b/bfd/libbfd.h
+index 3c184fcadadf..989f4bc0b595 100644
+--- a/bfd/libbfd.h
++++ b/bfd/libbfd.h
+@@ -2919,6 +2919,12 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
+   "BFD_RELOC_XTENSA_TLS_FUNC",
+   "BFD_RELOC_XTENSA_TLS_ARG",
+   "BFD_RELOC_XTENSA_TLS_CALL",
++  "BFD_RELOC_XTENSA_PDIFF8",
++  "BFD_RELOC_XTENSA_PDIFF16",
++  "BFD_RELOC_XTENSA_PDIFF32",
++  "BFD_RELOC_XTENSA_NDIFF8",
++  "BFD_RELOC_XTENSA_NDIFF16",
++  "BFD_RELOC_XTENSA_NDIFF32",
+   "BFD_RELOC_Z80_DISP8",
+   "BFD_RELOC_Z80_BYTE0",
+   "BFD_RELOC_Z80_BYTE1",
+diff --git a/bfd/reloc.c b/bfd/reloc.c
+index c4dec86d1d46..f5df8e2ab3eb 100644
+--- a/bfd/reloc.c
++++ b/bfd/reloc.c
+@@ -6556,6 +6556,8 @@ ENUMX
+ ENUMX
+   BFD_RELOC_XTENSA_DIFF32
+ ENUMDOC
++  Xtensa relocations for backward compatibility.  These have been replaced
++  by BFD_RELOC_XTENSA_PDIFF and BFD_RELOC_XTENSA_NDIFF.
+   Xtensa relocations to mark the difference of two local symbols.
+   These are only needed to support linker relaxation and can be ignored
+   when not relaxing.  The field is set to the value of the difference
+@@ -6668,6 +6670,28 @@ ENUMX
+   BFD_RELOC_XTENSA_TLS_CALL
+ ENUMDOC
+   Xtensa TLS relocations.
++ENUM
++  BFD_RELOC_XTENSA_PDIFF8
++ENUMX
++  BFD_RELOC_XTENSA_PDIFF16
++ENUMX
++  BFD_RELOC_XTENSA_PDIFF32
++ENUMX
++  BFD_RELOC_XTENSA_NDIFF8
++ENUMX
++  BFD_RELOC_XTENSA_NDIFF16
++ENUMX
++  BFD_RELOC_XTENSA_NDIFF32
++ENUMDOC
++  Xtensa relocations to mark the difference of two local symbols.
++  These are only needed to support linker relaxation and can be ignored
++  when not relaxing.  The field is set to the value of the difference
++  assuming no relaxation.  The relocation encodes the position of the
++  subtracted symbol so the linker can determine whether to adjust the field
++  value.  PDIFF relocations are used for positive differences, NDIFF
++  relocations are used for negative differences.  The difference value
++  is treated as unsigned with these relocation types, giving full
++  8/16 value ranges.
+ 
+ ENUM
+   BFD_RELOC_Z80_DISP8
+diff --git a/binutils/readelf.c b/binutils/readelf.c
+index d4756c93b345..800918f901c8 100644
+--- a/binutils/readelf.c
++++ b/binutils/readelf.c
+@@ -13262,7 +13262,13 @@ is_none_reloc (Filedata * filedata, unsigned int reloc_type)
+       return (reloc_type == 0      /* R_XTENSA_NONE.  */
+ 	      || reloc_type == 17  /* R_XTENSA_DIFF8.  */
+ 	      || reloc_type == 18  /* R_XTENSA_DIFF16.  */
+-	      || reloc_type == 19  /* R_XTENSA_DIFF32.  */);
++	      || reloc_type == 19  /* R_XTENSA_DIFF32.  */
++	      || reloc_type == 57  /* R_XTENSA_PDIFF8.  */
++	      || reloc_type == 58  /* R_XTENSA_PDIFF16.  */
++	      || reloc_type == 59  /* R_XTENSA_PDIFF32.  */
++	      || reloc_type == 60  /* R_XTENSA_NDIFF8.  */
++	      || reloc_type == 61  /* R_XTENSA_NDIFF16.  */
++	      || reloc_type == 62  /* R_XTENSA_NDIFF32.  */);
+     }
+   return FALSE;
+ }
+diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
+index 71d4d94a8d7d..ee75c13548ff 100644
+--- a/gas/config/tc-xtensa.c
++++ b/gas/config/tc-xtensa.c
+@@ -5974,18 +5974,24 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
+     case BFD_RELOC_8:
+       if (fixP->fx_subsy)
+ 	{
++	  bfd_boolean neg = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
++	    < S_GET_VALUE (fixP->fx_subsy);
++
+ 	  switch (fixP->fx_r_type)
+ 	    {
+ 	    case BFD_RELOC_8:
+-	      fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF8;
++	      fixP->fx_r_type = neg
++		? BFD_RELOC_XTENSA_NDIFF8 : BFD_RELOC_XTENSA_PDIFF8;
+ 	      fixP->fx_signed = 0;
+ 	      break;
+ 	    case BFD_RELOC_16:
+-	      fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF16;
++	      fixP->fx_r_type = neg
++		? BFD_RELOC_XTENSA_NDIFF16 : BFD_RELOC_XTENSA_PDIFF16;
+ 	      fixP->fx_signed = 0;
+ 	      break;
+ 	    case BFD_RELOC_32:
+-	      fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF32;
++	      fixP->fx_r_type = neg
++		? BFD_RELOC_XTENSA_NDIFF32 : BFD_RELOC_XTENSA_PDIFF32;
+ 	      fixP->fx_signed = 0;
+ 	      break;
+ 	    default:
+diff --git a/gas/testsuite/gas/xtensa/loc.d b/gas/testsuite/gas/xtensa/loc.d
+index 71983cc90055..8fb3425999d5 100644
+--- a/gas/testsuite/gas/xtensa/loc.d
++++ b/gas/testsuite/gas/xtensa/loc.d
+@@ -6,5 +6,5 @@
+ 
+ RELOCATION RECORDS FOR \[\.debug_line\]:
+ #...
+-.*R_XTENSA_DIFF16.*\.text\+0x00009c42
++.*R_XTENSA_PDIFF16.*\.text\+0x00009c42
+ #...
+diff --git a/include/elf/xtensa.h b/include/elf/xtensa.h
+index 2eb5e4e52941..bd5c80d13777 100644
+--- a/include/elf/xtensa.h
++++ b/include/elf/xtensa.h
+@@ -87,6 +87,12 @@ START_RELOC_NUMBERS (elf_xtensa_reloc_type)
+      RELOC_NUMBER (R_XTENSA_TLS_FUNC, 54)
+      RELOC_NUMBER (R_XTENSA_TLS_ARG, 55)
+      RELOC_NUMBER (R_XTENSA_TLS_CALL, 56)
++     RELOC_NUMBER (R_XTENSA_PDIFF8, 57)
++     RELOC_NUMBER (R_XTENSA_PDIFF16, 58)
++     RELOC_NUMBER (R_XTENSA_PDIFF32, 59)
++     RELOC_NUMBER (R_XTENSA_NDIFF8, 60)
++     RELOC_NUMBER (R_XTENSA_NDIFF16, 61)
++     RELOC_NUMBER (R_XTENSA_NDIFF32, 62)
+ END_RELOC_NUMBERS (R_XTENSA_max)
+ 
+ /* Processor-specific flags for the ELF header e_flags field.  */
+diff --git a/ld/testsuite/ld-xtensa/relax-loc.d b/ld/testsuite/ld-xtensa/relax-loc.d
+new file mode 100644
+index 000000000000..3c8d673732ff
+--- /dev/null
++++ b/ld/testsuite/ld-xtensa/relax-loc.d
+@@ -0,0 +1,7 @@
++#as: --text-section-literals
++#ld:
++#objdump: --dwarf=decodedline
++#...
++relax-loc.s[ 	]+1[ 	]+0x400054[ 	]+.*
++relax-loc.s[ 	]+2[ 	]+0x40005c[ 	]+.*
++#...
+diff --git a/ld/testsuite/ld-xtensa/relax-loc.s b/ld/testsuite/ld-xtensa/relax-loc.s
+new file mode 100644
+index 000000000000..d768470e287a
+--- /dev/null
++++ b/ld/testsuite/ld-xtensa/relax-loc.s
+@@ -0,0 +1,15 @@
++	.file	1 "relax-loc.s"
++	.globl	_start
++	.globl	_ResetVector
++	.text
++_ResetVector:
++_start:
++	.loc	1 1
++	j	1f
++	.literal_position
++1:
++	.loc	1 2
++
++	.rep	10000
++	movi	a2, 0x12345678
++	.endr
+diff --git a/ld/testsuite/ld-xtensa/xtensa.exp b/ld/testsuite/ld-xtensa/xtensa.exp
+index 9b2235b2151b..de39887936ad 100644
+--- a/ld/testsuite/ld-xtensa/xtensa.exp
++++ b/ld/testsuite/ld-xtensa/xtensa.exp
+@@ -27,6 +27,7 @@ run_dump_test "call_overflow"
+ run_dump_test "coalesce"
+ run_dump_test "diff_overflow"
+ run_dump_test "lcall"
++run_dump_test "relax-loc"
+ 
+ run_dump_test "relax-static-pie"
+ run_dump_test "relax-static-local-pie"
+-- 
+2.20.1
+

                 reply	other threads:[~2020-04-23 21:31 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200423211738.B63468FDF7@busybox.osuosl.org \
    --to=thomas.petazzoni@bootlin.com \
    --cc=buildroot@busybox.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.