Skip to content

Commit 30ce8e4

Browse files
committed
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 <[email protected]> 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.
1 parent e44f65e commit 30ce8e4

File tree

16 files changed

+228
-7
lines changed

16 files changed

+228
-7
lines changed

bfd/ChangeLog

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
2020-04-22 Max Filippov <[email protected]>
2+
3+
PR ld/25861
4+
* bfd-in2.h: Regenerated.
5+
* elf32-xtensa.c (elf_howto_table): New entries for
6+
R_XTENSA_PDIFF{8,16,32} and R_XTENSA_NDIFF{8,16,32}.
7+
(elf_xtensa_reloc_type_lookup, elf_xtensa_do_reloc)
8+
(relax_section): Add cases for R_XTENSA_PDIFF{8,16,32} and
9+
R_XTENSA_NDIFF{8,16,32}.
10+
* libbfd.h (bfd_reloc_code_real_names): Add names for
11+
BFD_RELOC_XTENSA_PDIFF{8,16,32} and
12+
BFD_RELOC_XTENSA_NDIFF{8,16,32}.
13+
* reloc.c: Add documentation for BFD_RELOC_XTENSA_PDIFF{8,16,32}
14+
and BFD_RELOC_XTENSA_NDIFF{8,16,32}.
15+
116
2020-04-21 Tamar Christina <[email protected]>
217

318
PR binutils/24753

bfd/bfd-in2.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5224,7 +5224,9 @@ to one of its own internal functions or data structures. */
52245224
PLT entries. Otherwise, this is just a generic 32-bit relocation. */
52255225
BFD_RELOC_XTENSA_PLT,
52265226

5227-
/* Xtensa relocations to mark the difference of two local symbols.
5227+
/* Xtensa relocations for backward compatibility. These have been replaced
5228+
by BFD_RELOC_XTENSA_PDIFF and BFD_RELOC_XTENSA_NDIFF.
5229+
Xtensa relocations to mark the difference of two local symbols.
52285230
These are only needed to support linker relaxation and can be ignored
52295231
when not relaxing. The field is set to the value of the difference
52305232
assuming no relaxation. The relocation encodes the position of the
@@ -5298,6 +5300,22 @@ BFD_RELOC_XTENSA_ASM_EXPAND. */
52985300
BFD_RELOC_XTENSA_TLS_ARG,
52995301
BFD_RELOC_XTENSA_TLS_CALL,
53005302

5303+
/* Xtensa relocations to mark the difference of two local symbols.
5304+
These are only needed to support linker relaxation and can be ignored
5305+
when not relaxing. The field is set to the value of the difference
5306+
assuming no relaxation. The relocation encodes the position of the
5307+
subtracted symbol so the linker can determine whether to adjust the field
5308+
value. PDIFF relocations are used for positive differences, NDIFF
5309+
relocations are used for negative differences. The difference value
5310+
is treated as unsigned with these relocation types, giving full
5311+
8/16 value ranges. */
5312+
BFD_RELOC_XTENSA_PDIFF8,
5313+
BFD_RELOC_XTENSA_PDIFF16,
5314+
BFD_RELOC_XTENSA_PDIFF32,
5315+
BFD_RELOC_XTENSA_NDIFF8,
5316+
BFD_RELOC_XTENSA_NDIFF16,
5317+
BFD_RELOC_XTENSA_NDIFF32,
5318+
53015319
/* 8 bit signed offset in (ix+d) or (iy+d). */
53025320
BFD_RELOC_Z80_DISP8,
53035321

bfd/elf32-xtensa.c

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,20 @@ static reloc_howto_type elf_howto_table[] =
325325
HOWTO (R_XTENSA_TLS_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
326326
bfd_elf_xtensa_reloc, "R_XTENSA_TLS_CALL",
327327
FALSE, 0, 0, FALSE),
328+
329+
HOWTO (R_XTENSA_PDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
330+
bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF8", FALSE, 0, 0xff, FALSE),
331+
HOWTO (R_XTENSA_PDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
332+
bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF16", FALSE, 0, 0xffff, FALSE),
333+
HOWTO (R_XTENSA_PDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
334+
bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF32", FALSE, 0, 0xffffffff, FALSE),
335+
336+
HOWTO (R_XTENSA_NDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
337+
bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF8", FALSE, 0, 0xff, FALSE),
338+
HOWTO (R_XTENSA_NDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
339+
bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF16", FALSE, 0, 0xffff, FALSE),
340+
HOWTO (R_XTENSA_NDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
341+
bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF32", FALSE, 0, 0xffffffff, FALSE),
328342
};
329343

330344
#if DEBUG_GEN_RELOC
@@ -364,6 +378,30 @@ elf_xtensa_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
364378
TRACE ("BFD_RELOC_XTENSA_DIFF32");
365379
return &elf_howto_table[(unsigned) R_XTENSA_DIFF32 ];
366380

381+
case BFD_RELOC_XTENSA_PDIFF8:
382+
TRACE ("BFD_RELOC_XTENSA_PDIFF8");
383+
return &elf_howto_table[(unsigned) R_XTENSA_PDIFF8 ];
384+
385+
case BFD_RELOC_XTENSA_PDIFF16:
386+
TRACE ("BFD_RELOC_XTENSA_PDIFF16");
387+
return &elf_howto_table[(unsigned) R_XTENSA_PDIFF16 ];
388+
389+
case BFD_RELOC_XTENSA_PDIFF32:
390+
TRACE ("BFD_RELOC_XTENSA_PDIFF32");
391+
return &elf_howto_table[(unsigned) R_XTENSA_PDIFF32 ];
392+
393+
case BFD_RELOC_XTENSA_NDIFF8:
394+
TRACE ("BFD_RELOC_XTENSA_NDIFF8");
395+
return &elf_howto_table[(unsigned) R_XTENSA_NDIFF8 ];
396+
397+
case BFD_RELOC_XTENSA_NDIFF16:
398+
TRACE ("BFD_RELOC_XTENSA_NDIFF16");
399+
return &elf_howto_table[(unsigned) R_XTENSA_NDIFF16 ];
400+
401+
case BFD_RELOC_XTENSA_NDIFF32:
402+
TRACE ("BFD_RELOC_XTENSA_NDIFF32");
403+
return &elf_howto_table[(unsigned) R_XTENSA_NDIFF32 ];
404+
367405
case BFD_RELOC_XTENSA_RTLD:
368406
TRACE ("BFD_RELOC_XTENSA_RTLD");
369407
return &elf_howto_table[(unsigned) R_XTENSA_RTLD ];
@@ -1851,6 +1889,12 @@ elf_xtensa_do_reloc (reloc_howto_type *howto,
18511889
case R_XTENSA_DIFF8:
18521890
case R_XTENSA_DIFF16:
18531891
case R_XTENSA_DIFF32:
1892+
case R_XTENSA_PDIFF8:
1893+
case R_XTENSA_PDIFF16:
1894+
case R_XTENSA_PDIFF32:
1895+
case R_XTENSA_NDIFF8:
1896+
case R_XTENSA_NDIFF16:
1897+
case R_XTENSA_NDIFF32:
18541898
case R_XTENSA_TLS_FUNC:
18551899
case R_XTENSA_TLS_ARG:
18561900
case R_XTENSA_TLS_CALL:
@@ -9604,7 +9648,13 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
96049648

96059649
if (r_type == R_XTENSA_DIFF8
96069650
|| r_type == R_XTENSA_DIFF16
9607-
|| r_type == R_XTENSA_DIFF32)
9651+
|| r_type == R_XTENSA_DIFF32
9652+
|| r_type == R_XTENSA_PDIFF8
9653+
|| r_type == R_XTENSA_PDIFF16
9654+
|| r_type == R_XTENSA_PDIFF32
9655+
|| r_type == R_XTENSA_NDIFF8
9656+
|| r_type == R_XTENSA_NDIFF16
9657+
|| r_type == R_XTENSA_NDIFF32)
96089658
{
96099659
bfd_signed_vma diff_value = 0;
96109660
bfd_vma new_end_offset, diff_mask = 0;
@@ -9631,8 +9681,27 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
96319681
diff_value =
96329682
bfd_get_signed_32 (abfd, &contents[old_source_offset]);
96339683
break;
9684+
case R_XTENSA_PDIFF8:
9685+
case R_XTENSA_NDIFF8:
9686+
diff_value =
9687+
bfd_get_8 (abfd, &contents[old_source_offset]);
9688+
break;
9689+
case R_XTENSA_PDIFF16:
9690+
case R_XTENSA_NDIFF16:
9691+
diff_value =
9692+
bfd_get_16 (abfd, &contents[old_source_offset]);
9693+
break;
9694+
case R_XTENSA_PDIFF32:
9695+
case R_XTENSA_NDIFF32:
9696+
diff_value =
9697+
bfd_get_32 (abfd, &contents[old_source_offset]);
9698+
break;
96349699
}
96359700

9701+
if (r_type >= R_XTENSA_NDIFF8
9702+
&& r_type <= R_XTENSA_NDIFF32)
9703+
diff_value = -diff_value;
9704+
96369705
new_end_offset = offset_with_removed_text_map
96379706
(&target_relax_info->action_list,
96389707
r_rel.target_offset + diff_value);
@@ -9655,6 +9724,24 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
96559724
bfd_put_signed_32 (abfd, diff_value,
96569725
&contents[old_source_offset]);
96579726
break;
9727+
case R_XTENSA_PDIFF8:
9728+
case R_XTENSA_NDIFF8:
9729+
diff_mask = 0xff;
9730+
bfd_put_8 (abfd, diff_value,
9731+
&contents[old_source_offset]);
9732+
break;
9733+
case R_XTENSA_PDIFF16:
9734+
case R_XTENSA_NDIFF16:
9735+
diff_mask = 0xffff;
9736+
bfd_put_16 (abfd, diff_value,
9737+
&contents[old_source_offset]);
9738+
break;
9739+
case R_XTENSA_PDIFF32:
9740+
case R_XTENSA_NDIFF32:
9741+
diff_mask = 0xffffffff;
9742+
bfd_put_32 (abfd, diff_value,
9743+
&contents[old_source_offset]);
9744+
break;
96589745
}
96599746

96609747
/* Check for overflow. Sign bits must be all zeroes or all ones */

bfd/libbfd.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2919,6 +2919,12 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
29192919
"BFD_RELOC_XTENSA_TLS_FUNC",
29202920
"BFD_RELOC_XTENSA_TLS_ARG",
29212921
"BFD_RELOC_XTENSA_TLS_CALL",
2922+
"BFD_RELOC_XTENSA_PDIFF8",
2923+
"BFD_RELOC_XTENSA_PDIFF16",
2924+
"BFD_RELOC_XTENSA_PDIFF32",
2925+
"BFD_RELOC_XTENSA_NDIFF8",
2926+
"BFD_RELOC_XTENSA_NDIFF16",
2927+
"BFD_RELOC_XTENSA_NDIFF32",
29222928
"BFD_RELOC_Z80_DISP8",
29232929
"BFD_RELOC_Z80_BYTE0",
29242930
"BFD_RELOC_Z80_BYTE1",

bfd/reloc.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6556,6 +6556,8 @@ ENUMX
65566556
ENUMX
65576557
BFD_RELOC_XTENSA_DIFF32
65586558
ENUMDOC
6559+
Xtensa relocations for backward compatibility. These have been replaced
6560+
by BFD_RELOC_XTENSA_PDIFF and BFD_RELOC_XTENSA_NDIFF.
65596561
Xtensa relocations to mark the difference of two local symbols.
65606562
These are only needed to support linker relaxation and can be ignored
65616563
when not relaxing. The field is set to the value of the difference
@@ -6668,6 +6670,28 @@ ENUMX
66686670
BFD_RELOC_XTENSA_TLS_CALL
66696671
ENUMDOC
66706672
Xtensa TLS relocations.
6673+
ENUM
6674+
BFD_RELOC_XTENSA_PDIFF8
6675+
ENUMX
6676+
BFD_RELOC_XTENSA_PDIFF16
6677+
ENUMX
6678+
BFD_RELOC_XTENSA_PDIFF32
6679+
ENUMX
6680+
BFD_RELOC_XTENSA_NDIFF8
6681+
ENUMX
6682+
BFD_RELOC_XTENSA_NDIFF16
6683+
ENUMX
6684+
BFD_RELOC_XTENSA_NDIFF32
6685+
ENUMDOC
6686+
Xtensa relocations to mark the difference of two local symbols.
6687+
These are only needed to support linker relaxation and can be ignored
6688+
when not relaxing. The field is set to the value of the difference
6689+
assuming no relaxation. The relocation encodes the position of the
6690+
subtracted symbol so the linker can determine whether to adjust the field
6691+
value. PDIFF relocations are used for positive differences, NDIFF
6692+
relocations are used for negative differences. The difference value
6693+
is treated as unsigned with these relocation types, giving full
6694+
8/16 value ranges.
66716695
66726696
ENUM
66736697
BFD_RELOC_Z80_DISP8

binutils/ChangeLog

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2020-04-22 Max Filippov <[email protected]>
2+
3+
PR ld/25861
4+
* readelf.c (is_none_reloc): Recognize
5+
BFD_RELOC_XTENSA_PDIFF{8,16,32} and
6+
BFD_RELOC_XTENSA_NDIFF{8,16,32}.
7+
18
2020-04-22 Nick Clifton <[email protected]>
29

310
* MAINTAINERS: Remove Chris Faylor as the ix86 PE maintainer.

binutils/readelf.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13348,7 +13348,13 @@ is_none_reloc (Filedata * filedata, unsigned int reloc_type)
1334813348
return (reloc_type == 0 /* R_XTENSA_NONE. */
1334913349
|| reloc_type == 17 /* R_XTENSA_DIFF8. */
1335013350
|| reloc_type == 18 /* R_XTENSA_DIFF16. */
13351-
|| reloc_type == 19 /* R_XTENSA_DIFF32. */);
13351+
|| reloc_type == 19 /* R_XTENSA_DIFF32. */
13352+
|| reloc_type == 57 /* R_XTENSA_PDIFF8. */
13353+
|| reloc_type == 58 /* R_XTENSA_PDIFF16. */
13354+
|| reloc_type == 59 /* R_XTENSA_PDIFF32. */
13355+
|| reloc_type == 60 /* R_XTENSA_NDIFF8. */
13356+
|| reloc_type == 61 /* R_XTENSA_NDIFF16. */
13357+
|| reloc_type == 62 /* R_XTENSA_NDIFF32. */);
1335213358
}
1335313359
return FALSE;
1335413360
}

gas/ChangeLog

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
2020-04-22 Max Filippov <[email protected]>
2+
3+
PR ld/25861
4+
* config/tc-xtensa.c (md_apply_fix): Replace
5+
BFD_RELOC_XTENSA_DIFF{8,16,32} generation with
6+
BFD_RELOC_XTENSA_PDIFF{8,16,32} and
7+
BFD_RELOC_XTENSA_NDIFF{8,16,32} generation.
8+
* testsuite/gas/xtensa/loc.d: Replace BFD_RELOC_XTENSA_DIFF16
9+
with BFD_RELOC_XTENSA_PDIFF16 in the expected output.
10+
111
2020-04-22 Alan Modra <[email protected]>
212

313
* config/obj-elf.c (elf_frob_symbol): Unconditionally remove

gas/config/tc-xtensa.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5974,18 +5974,24 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
59745974
case BFD_RELOC_8:
59755975
if (fixP->fx_subsy)
59765976
{
5977+
bfd_boolean neg = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
5978+
< S_GET_VALUE (fixP->fx_subsy);
5979+
59775980
switch (fixP->fx_r_type)
59785981
{
59795982
case BFD_RELOC_8:
5980-
fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF8;
5983+
fixP->fx_r_type = neg
5984+
? BFD_RELOC_XTENSA_NDIFF8 : BFD_RELOC_XTENSA_PDIFF8;
59815985
fixP->fx_signed = 0;
59825986
break;
59835987
case BFD_RELOC_16:
5984-
fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF16;
5988+
fixP->fx_r_type = neg
5989+
? BFD_RELOC_XTENSA_NDIFF16 : BFD_RELOC_XTENSA_PDIFF16;
59855990
fixP->fx_signed = 0;
59865991
break;
59875992
case BFD_RELOC_32:
5988-
fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF32;
5993+
fixP->fx_r_type = neg
5994+
? BFD_RELOC_XTENSA_NDIFF32 : BFD_RELOC_XTENSA_PDIFF32;
59895995
fixP->fx_signed = 0;
59905996
break;
59915997
default:

gas/testsuite/gas/xtensa/loc.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66

77
RELOCATION RECORDS FOR \[\.debug_line\]:
88
#...
9-
.*R_XTENSA_DIFF16.*\.text\+0x00009c42
9+
.*R_XTENSA_PDIFF16.*\.text\+0x00009c42
1010
#...

0 commit comments

Comments
 (0)