From: Max Filippov Date: Mon, 20 Apr 2020 02:04:41 +0000 (-0700) Subject: xtensa: fix PR ld/25861 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=30ce8e47fad9b057b6d7af9e1d43061126d34d20;p=binutils-gdb.git 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. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 07124149523..adba80c8384 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,18 @@ +2020-04-22 Max Filippov + + PR ld/25861 + * 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}. + 2020-04-21 Tamar Christina PR binutils/24753 diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 8693f86dd43..ec23fd49870 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -5224,7 +5224,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 @@ -5298,6 +5300,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 473a9d76f28..fded42d52a9 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 348ccfd4b57..6aeaf187e2b 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 c4dec86d1d4..f5df8e2ab3e 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/ChangeLog b/binutils/ChangeLog index 3b9729ab248..07626115c53 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,10 @@ +2020-04-22 Max Filippov + + PR ld/25861 + * readelf.c (is_none_reloc): Recognize + BFD_RELOC_XTENSA_PDIFF{8,16,32} and + BFD_RELOC_XTENSA_NDIFF{8,16,32}. + 2020-04-22 Nick Clifton * MAINTAINERS: Remove Chris Faylor as the ix86 PE maintainer. diff --git a/binutils/readelf.c b/binutils/readelf.c index 32538634453..4f80bd94b93 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -13348,7 +13348,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/ChangeLog b/gas/ChangeLog index 3f59c816145..f31504b864d 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2020-04-22 Max Filippov + + PR ld/25861 + * 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. + 2020-04-22 Alan Modra * config/obj-elf.c (elf_frob_symbol): Unconditionally remove diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c index 71d4d94a8d7..ee75c13548f 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 71983cc9005..8fb3425999d 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/ChangeLog b/include/ChangeLog index 1829ec55996..bf379cc2b64 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,9 @@ +2020-04-22 Max Filippov + + PR ld/25861 + * elf/xtensa.h (elf_xtensa_reloc_type): New entries for + R_XTENSA_PDIFF{8,16,32} and R_XTENSA_NDIFF{8,16,32}. + 2020-04-21 Alan Modra * elf/sh.h (STO_SH5_ISA32, SHF_SH5_ISA32, SHF_SH5_ISA32_MIXED), diff --git a/include/elf/xtensa.h b/include/elf/xtensa.h index 2eb5e4e5294..bd5c80d1377 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/ChangeLog b/ld/ChangeLog index 341ad1d90dc..77551f0f4e1 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,10 @@ +2020-04-22 Max Filippov + + PR ld/25861 + * 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. + 2020-04-22 Fangrui Song PR ld/25806 diff --git a/ld/testsuite/ld-xtensa/relax-loc.d b/ld/testsuite/ld-xtensa/relax-loc.d new file mode 100644 index 00000000000..3c8d673732f --- /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 00000000000..d768470e287 --- /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 9b2235b2151..de39887936a 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"