diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2020-04-19 19:04:41 -0700 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2020-04-22 18:46:45 -0700 |
commit | 30ce8e47fad9b057b6d7af9e1d43061126d34d20 (patch) | |
tree | f1c9ab86407f5a80c78bdf436f2178d2aacc96dd /bfd/elf32-xtensa.c | |
parent | e44f65e3c5c9473d0dd98efa8c142d361b1273d7 (diff) | |
download | gdb-30ce8e47fad9b057b6d7af9e1d43061126d34d20.zip gdb-30ce8e47fad9b057b6d7af9e1d43061126d34d20.tar.gz gdb-30ce8e47fad9b057b6d7af9e1d43061126d34d20.tar.bz2 |
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.
Diffstat (limited to 'bfd/elf32-xtensa.c')
-rw-r--r-- | bfd/elf32-xtensa.c | 89 |
1 files changed, 88 insertions, 1 deletions
diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c index 473a9d7..fded42d 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 */ |