aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-xtensa.c
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2020-04-19 19:04:41 -0700
committerMax Filippov <jcmvbkbc@gmail.com>2020-04-22 18:46:45 -0700
commit30ce8e47fad9b057b6d7af9e1d43061126d34d20 (patch)
treef1c9ab86407f5a80c78bdf436f2178d2aacc96dd /bfd/elf32-xtensa.c
parente44f65e3c5c9473d0dd98efa8c142d361b1273d7 (diff)
downloadgdb-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.c89
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 */