Skip to content

Commit 7ea90d9

Browse files
amodramaciej-w-rozycki
authored andcommitted
MIPS: Fix linker for REL TLS HI16/LO16 relocs
With REL targets TLS HI16/LO16 relocations need to combine the low part with the high part just as all the remaining HI16/LO16 relocations, so as to determine the borrow in calculation correctly. 2025-07-12 Alan Modra <[email protected]> bfd/ PR 19977 * elfxx-mips.c (tls_hi16_reloc_p): New function. (mips_elf_add_lo16_rel_addend): Handle tls relocs. (_bfd_mips_elf_relocate_section): Likewise. 2025-07-12 Maciej W. Rozycki <[email protected]> ld/ PR 19977 * testsuite/ld-mips-elf/pr19977.d: New test. * testsuite/ld-mips-elf/pr19977-mips16.d: New test. * testsuite/ld-mips-elf/pr19977-micromips.d: New test. * testsuite/ld-mips-elf/pr19977-r.d: New test. * testsuite/ld-mips-elf/pr19977-r-mips16.d: New test. * testsuite/ld-mips-elf/pr19977-r-micromips.d: New test. * testsuite/ld-mips-elf/pr19977-r.s: New test source. * testsuite/ld-mips-elf/pr19977.ld: New test linker script. * testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
1 parent 78f28b6 commit 7ea90d9

File tree

10 files changed

+199
-10
lines changed

10 files changed

+199
-10
lines changed

bfd/elfxx-mips.c

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2293,6 +2293,17 @@ lo16_reloc_p (int r_type)
22932293
|| r_type == R_MIPS_PCLO16);
22942294
}
22952295

2296+
static inline bool
2297+
tls_hi16_reloc_p (int r_type)
2298+
{
2299+
return (r_type == R_MIPS_TLS_DTPREL_HI16
2300+
|| r_type == R_MIPS_TLS_TPREL_HI16
2301+
|| r_type == R_MIPS16_TLS_DTPREL_HI16
2302+
|| r_type == R_MIPS16_TLS_TPREL_HI16
2303+
|| r_type == R_MICROMIPS_TLS_DTPREL_HI16
2304+
|| r_type == R_MICROMIPS_TLS_TPREL_HI16);
2305+
}
2306+
22962307
static inline bool
22972308
mips16_call_reloc_p (int r_type)
22982309
{
@@ -8312,14 +8323,44 @@ mips_elf_add_lo16_rel_addend (bfd *abfd,
83128323
bfd_vma l;
83138324

83148325
r_type = ELF_R_TYPE (abfd, rel->r_info);
8315-
if (mips16_reloc_p (r_type))
8316-
lo16_type = R_MIPS16_LO16;
8317-
else if (micromips_reloc_p (r_type))
8318-
lo16_type = R_MICROMIPS_LO16;
8319-
else if (r_type == R_MIPS_PCHI16)
8320-
lo16_type = R_MIPS_PCLO16;
8321-
else
8322-
lo16_type = R_MIPS_LO16;
8326+
switch (r_type)
8327+
{
8328+
case R_MIPS_HI16:
8329+
case R_MIPS_GOT16:
8330+
lo16_type = R_MIPS_LO16;
8331+
break;
8332+
case R_MIPS_PCHI16:
8333+
lo16_type = R_MIPS_PCLO16;
8334+
break;
8335+
case R_MIPS_TLS_DTPREL_HI16:
8336+
lo16_type = R_MIPS_TLS_DTPREL_LO16;
8337+
break;
8338+
case R_MIPS_TLS_TPREL_HI16:
8339+
lo16_type = R_MIPS_TLS_TPREL_LO16;
8340+
break;
8341+
case R_MIPS16_HI16:
8342+
case R_MIPS16_GOT16:
8343+
lo16_type = R_MIPS16_LO16;
8344+
break;
8345+
case R_MIPS16_TLS_DTPREL_HI16:
8346+
lo16_type = R_MIPS16_TLS_DTPREL_LO16;
8347+
break;
8348+
case R_MIPS16_TLS_TPREL_HI16:
8349+
lo16_type = R_MIPS16_TLS_TPREL_LO16;
8350+
break;
8351+
case R_MICROMIPS_HI16:
8352+
case R_MICROMIPS_GOT16:
8353+
lo16_type = R_MICROMIPS_LO16;
8354+
break;
8355+
case R_MICROMIPS_TLS_DTPREL_HI16:
8356+
lo16_type = R_MICROMIPS_TLS_DTPREL_LO16;
8357+
break;
8358+
case R_MICROMIPS_TLS_TPREL_HI16:
8359+
lo16_type = R_MICROMIPS_TLS_TPREL_LO16;
8360+
break;
8361+
default:
8362+
abort ();
8363+
}
83238364

83248365
/* The combined value is the sum of the HI16 addend, left-shifted by
83258366
sixteen bits, and the LO16 addend, sign extended. (Usually, the
@@ -10547,7 +10588,8 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
1054710588
if (hi16_reloc_p (r_type)
1054810589
|| (got16_reloc_p (r_type)
1054910590
&& mips_elf_local_relocation_p (input_bfd, rel,
10550-
local_sections)))
10591+
local_sections))
10592+
|| tls_hi16_reloc_p (r_type))
1055110593
{
1055210594
if (!mips_elf_add_lo16_rel_addend (input_bfd, input_section,
1055310595
rel, relend,
@@ -10585,7 +10627,9 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
1058510627
if (!rela_relocation_p && rel->r_addend)
1058610628
{
1058710629
addend += rel->r_addend;
10588-
if (hi16_reloc_p (r_type) || got16_reloc_p (r_type))
10630+
if (hi16_reloc_p (r_type)
10631+
|| got16_reloc_p (r_type)
10632+
|| tls_hi16_reloc_p (r_type))
1058910633
addend = mips_elf_high (addend);
1059010634
else if (r_type == R_MIPS_HIGHER)
1059110635
addend = mips_elf_higher (addend);

ld/testsuite/ld-mips-elf/mips-elf.exp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,16 @@ run_dump_test_n64 "pcrel-hilo-srec" \
867867
[list [list name (n64)] \
868868
[list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
869869

870+
run_dump_test_o32 "pr19977"
871+
run_dump_test_n32 "pr19977" [list [list name (n32)]]
872+
run_dump_test_o32 "pr19977-mips16" noarch
873+
run_dump_test_n32 "pr19977-mips16" [list noarch [list name (n32)]]
874+
run_dump_test_o32 "pr19977-micromips" noarch
875+
run_dump_test_n32 "pr19977-micromips" [list noarch [list name (n32)]]
876+
run_dump_test_o32 "pr19977-r"
877+
run_dump_test_o32 "pr19977-r-mips16" noarch
878+
run_dump_test_o32 "pr19977-r-micromips" noarch
879+
870880
if { $linux_gnu } {
871881
run_dump_test_n32 "textrel-1"
872882
run_dump_test "got-page-1"
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#name: pr19977 microMIPS
2+
#source: ../../../gas/testsuite/gas/mips/pr19977.s
3+
#as: -mmicromips -march=mips64r2
4+
#objdump: -d
5+
#ld: -Tpr19977.ld -e 0 -N
6+
#notarget: mips*el-ps2-elf*
7+
8+
.*: file format elf.*mips.*
9+
10+
Disassembly of section \.text:
11+
12+
10000000 <[^>]*>:
13+
10000000: 3060 1122 li v1,4386
14+
10000004: 0063 8000 sll v1,v1,0x10
15+
10000008: 3063 2988 addiu v1,v1,10632
16+
1000000c: 3060 1122 li v1,4386
17+
10000010: 0063 8000 sll v1,v1,0x10
18+
10000014: 3063 1988 addiu v1,v1,6536
19+
10000018: 3060 1122 li v1,4386
20+
1000001c: 0063 8000 sll v1,v1,0x10
21+
10000020: 3063 a988 addiu v1,v1,-22136
22+
10000024: 3060 1122 li v1,4386
23+
10000028: 0063 8000 sll v1,v1,0x10
24+
1000002c: 3063 9988 addiu v1,v1,-26232
25+
#pass
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#name: pr19977 MIPS16
2+
#source: ../../../gas/testsuite/gas/mips/pr19977.s
3+
#as: -mips16 -march=mips3
4+
#objdump: -d
5+
#ld: -Tpr19977.ld -e 0 -N
6+
7+
.*: file format elf.*mips.*
8+
9+
Disassembly of section \.text:
10+
11+
10000000 <[^>]*>:
12+
10000000: f122 6b02 li v1,4386
13+
10000004: f400 3360 sll v1,16
14+
10000008: f185 4b08 addiu v1,10632
15+
1000000c: f122 6b02 li v1,4386
16+
10000010: f400 3360 sll v1,16
17+
10000014: f183 4b08 addiu v1,6536
18+
10000018: f122 6b02 li v1,4386
19+
1000001c: f400 3360 sll v1,16
20+
10000020: f195 4b08 addiu v1,-22136
21+
10000024: f122 6b02 li v1,4386
22+
10000028: f400 3360 sll v1,16
23+
1000002c: f193 4b08 addiu v1,-26232
24+
#pass
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#name: pr19977 microMIPS -r
2+
#source: pr19977-r.s
3+
#source: ../../../gas/testsuite/gas/mips/pr19977.s
4+
#as: -mmicromips -march=mips64r2
5+
#objdump: -dr
6+
#ld: -r
7+
#notarget: mips*el-ps2-elf*
8+
#dump: pr19977-r.d
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#name: pr19977 MIPS16 -r
2+
#source: pr19977-r.s
3+
#source: ../../../gas/testsuite/gas/mips/pr19977.s
4+
#as: -mips16 -march=mips3
5+
#objdump: -dr
6+
#ld: -r
7+
#dump: pr19977-r.d
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#name: pr19977 MIPS -r
2+
#source: pr19977-r.s
3+
#source: ../../../gas/testsuite/gas/mips/pr19977.s
4+
#objdump: -dr
5+
#ld: -r
6+
7+
.*
8+
9+
Disassembly of section \.text:
10+
11+
0+ <foo>:
12+
0: .* li v1,4387
13+
0: R_(|MICRO)MIPS(|16)_TLS_TPREL_HI16 \$loc0
14+
4: .* sll .*
15+
8: .* addiu v1(|,v1),-26232
16+
8: R_(|MICRO)MIPS(|16)_TLS_TPREL_LO16 \$loc0
17+
c: .* li v1,4387
18+
c: R_(|MICRO)MIPS(|16)_TLS_DTPREL_HI16 \$loc0
19+
10: .* sll .*
20+
14: .* addiu v1(|,v1),-26232
21+
14: R_(|MICRO)MIPS(|16)_TLS_DTPREL_LO16 \$loc0
22+
18: .* li v1,4387
23+
18: R_(|MICRO)MIPS(|16)_TLS_TPREL_HI16 \.tdata
24+
1c: .* sll .*
25+
20: .* addiu v1(|,v1),-30328
26+
20: R_(|MICRO)MIPS(|16)_TLS_TPREL_LO16 \.tdata
27+
24: .* li v1,4387
28+
24: R_(|MICRO)MIPS(|16)_TLS_DTPREL_HI16 \.tdata
29+
28: .* sll .*
30+
2c: .* addiu v1(|,v1),-30328
31+
2c: R_(|MICRO)MIPS(|16)_TLS_DTPREL_LO16 \.tdata
32+
#pass
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.section .tdata,"awT",%progbits
2+
.space 28672

ld/testsuite/ld-mips-elf/pr19977.d

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#name: pr19977 MIPS
2+
#source: ../../../gas/testsuite/gas/mips/pr19977.s
3+
#objdump: -d
4+
#ld: -Tpr19977.ld -e 0 -N
5+
6+
.*: file format elf.*mips.*
7+
8+
Disassembly of section \.text:
9+
10+
10000000 <[^>]*>:
11+
10000000: 24031122 li v1,4386
12+
10000004: 00031c00 sll v1,v1,0x10
13+
10000008: 24632988 addiu v1,v1,10632
14+
1000000c: 24031122 li v1,4386
15+
10000010: 00031c00 sll v1,v1,0x10
16+
10000014: 24631988 addiu v1,v1,6536
17+
10000018: 24031122 li v1,4386
18+
1000001c: 00031c00 sll v1,v1,0x10
19+
10000020: 2463a988 addiu v1,v1,-22136
20+
10000024: 24031122 li v1,4386
21+
10000028: 00031c00 sll v1,v1,0x10
22+
1000002c: 24639988 addiu v1,v1,-26232
23+
#pass
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
MEMORY
2+
{
3+
text (rx) : ORIGIN = 0x10000000, LENGTH = 0x40000
4+
data (w) : ORIGIN = 0x34560000, LENGTH = 0x40000
5+
}
6+
SECTIONS
7+
{
8+
.text : { *(.text) } >text
9+
.tdata : { *(.tdata) } >data
10+
.symtab : { *(.symtab) }
11+
.strtab : { *(.strtab) }
12+
.shstrtab : { *(.shstrtab) }
13+
/DISCARD/ : { *(*) }
14+
}

0 commit comments

Comments
 (0)