From: Max Filippov Date: Thu, 23 Apr 2020 03:11:45 +0000 (-0700) Subject: package/binutils: fix xtensa PR ld/25861 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f0291ef4aba0954542000f40bbf3c67641f33011;p=buildroot.git package/binutils: fix xtensa PR ld/25861 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 Signed-off-by: Thomas Petazzoni --- 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 +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 +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 +--- +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 +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 +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 +--- +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 +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 +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 +--- +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 +