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.
This commit is contained in:
Max Filippov 2020-04-19 19:04:41 -07:00
parent e44f65e3c5
commit 30ce8e47fa
16 changed files with 228 additions and 7 deletions

View File

@ -1,3 +1,18 @@
2020-04-22 Max Filippov <jcmvbkbc@gmail.com>
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 <tamar.christina@arm.com>
PR binutils/24753

View File

@ -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,

View File

@ -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 */

View File

@ -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",

View File

@ -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

View File

@ -1,3 +1,10 @@
2020-04-22 Max Filippov <jcmvbkbc@gmail.com>
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 <nickc@redhat.com>
* MAINTAINERS: Remove Chris Faylor as the ix86 PE maintainer.

View File

@ -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;
}

View File

@ -1,3 +1,13 @@
2020-04-22 Max Filippov <jcmvbkbc@gmail.com>
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 <amodra@gmail.com>
* config/obj-elf.c (elf_frob_symbol): Unconditionally remove

View File

@ -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:

View File

@ -6,5 +6,5 @@
RELOCATION RECORDS FOR \[\.debug_line\]:
#...
.*R_XTENSA_DIFF16.*\.text\+0x00009c42
.*R_XTENSA_PDIFF16.*\.text\+0x00009c42
#...

View File

@ -1,3 +1,9 @@
2020-04-22 Max Filippov <jcmvbkbc@gmail.com>
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 <amodra@gmail.com>
* elf/sh.h (STO_SH5_ISA32, SHF_SH5_ISA32, SHF_SH5_ISA32_MIXED),

View File

@ -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. */

View File

@ -1,3 +1,10 @@
2020-04-22 Max Filippov <jcmvbkbc@gmail.com>
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 <maskray@google.com>
PR ld/25806

View File

@ -0,0 +1,7 @@
#as: --text-section-literals
#ld:
#objdump: --dwarf=decodedline
#...
relax-loc.s[ ]+1[ ]+0x400054[ ]+.*
relax-loc.s[ ]+2[ ]+0x40005c[ ]+.*
#...

View File

@ -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

View File

@ -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"