From 7ea90d9316d375924b342485eb0cf99d268bf62f Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sat, 12 Jul 2025 01:25:53 +0100 Subject: [PATCH] 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 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 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. --- bfd/elfxx-mips.c | 64 ++++++++++++++++--- ld/testsuite/ld-mips-elf/mips-elf.exp | 10 +++ ld/testsuite/ld-mips-elf/pr19977-micromips.d | 25 ++++++++ ld/testsuite/ld-mips-elf/pr19977-mips16.d | 24 +++++++ .../ld-mips-elf/pr19977-r-micromips.d | 8 +++ ld/testsuite/ld-mips-elf/pr19977-r-mips16.d | 7 ++ ld/testsuite/ld-mips-elf/pr19977-r.d | 32 ++++++++++ ld/testsuite/ld-mips-elf/pr19977-r.s | 2 + ld/testsuite/ld-mips-elf/pr19977.d | 23 +++++++ ld/testsuite/ld-mips-elf/pr19977.ld | 14 ++++ 10 files changed, 199 insertions(+), 10 deletions(-) create mode 100644 ld/testsuite/ld-mips-elf/pr19977-micromips.d create mode 100644 ld/testsuite/ld-mips-elf/pr19977-mips16.d create mode 100644 ld/testsuite/ld-mips-elf/pr19977-r-micromips.d create mode 100644 ld/testsuite/ld-mips-elf/pr19977-r-mips16.d create mode 100644 ld/testsuite/ld-mips-elf/pr19977-r.d create mode 100644 ld/testsuite/ld-mips-elf/pr19977-r.s create mode 100644 ld/testsuite/ld-mips-elf/pr19977.d create mode 100644 ld/testsuite/ld-mips-elf/pr19977.ld diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 7d1dff1d721..3c38f51aefd 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -2293,6 +2293,17 @@ lo16_reloc_p (int r_type) || r_type == R_MIPS_PCLO16); } +static inline bool +tls_hi16_reloc_p (int r_type) +{ + return (r_type == R_MIPS_TLS_DTPREL_HI16 + || r_type == R_MIPS_TLS_TPREL_HI16 + || r_type == R_MIPS16_TLS_DTPREL_HI16 + || r_type == R_MIPS16_TLS_TPREL_HI16 + || r_type == R_MICROMIPS_TLS_DTPREL_HI16 + || r_type == R_MICROMIPS_TLS_TPREL_HI16); +} + static inline bool mips16_call_reloc_p (int r_type) { @@ -8312,14 +8323,44 @@ mips_elf_add_lo16_rel_addend (bfd *abfd, bfd_vma l; r_type = ELF_R_TYPE (abfd, rel->r_info); - if (mips16_reloc_p (r_type)) - lo16_type = R_MIPS16_LO16; - else if (micromips_reloc_p (r_type)) - lo16_type = R_MICROMIPS_LO16; - else if (r_type == R_MIPS_PCHI16) - lo16_type = R_MIPS_PCLO16; - else - lo16_type = R_MIPS_LO16; + switch (r_type) + { + case R_MIPS_HI16: + case R_MIPS_GOT16: + lo16_type = R_MIPS_LO16; + break; + case R_MIPS_PCHI16: + lo16_type = R_MIPS_PCLO16; + break; + case R_MIPS_TLS_DTPREL_HI16: + lo16_type = R_MIPS_TLS_DTPREL_LO16; + break; + case R_MIPS_TLS_TPREL_HI16: + lo16_type = R_MIPS_TLS_TPREL_LO16; + break; + case R_MIPS16_HI16: + case R_MIPS16_GOT16: + lo16_type = R_MIPS16_LO16; + break; + case R_MIPS16_TLS_DTPREL_HI16: + lo16_type = R_MIPS16_TLS_DTPREL_LO16; + break; + case R_MIPS16_TLS_TPREL_HI16: + lo16_type = R_MIPS16_TLS_TPREL_LO16; + break; + case R_MICROMIPS_HI16: + case R_MICROMIPS_GOT16: + lo16_type = R_MICROMIPS_LO16; + break; + case R_MICROMIPS_TLS_DTPREL_HI16: + lo16_type = R_MICROMIPS_TLS_DTPREL_LO16; + break; + case R_MICROMIPS_TLS_TPREL_HI16: + lo16_type = R_MICROMIPS_TLS_TPREL_LO16; + break; + default: + abort (); + } /* The combined value is the sum of the HI16 addend, left-shifted by 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, if (hi16_reloc_p (r_type) || (got16_reloc_p (r_type) && mips_elf_local_relocation_p (input_bfd, rel, - local_sections))) + local_sections)) + || tls_hi16_reloc_p (r_type)) { if (!mips_elf_add_lo16_rel_addend (input_bfd, input_section, rel, relend, @@ -10585,7 +10627,9 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if (!rela_relocation_p && rel->r_addend) { addend += rel->r_addend; - if (hi16_reloc_p (r_type) || got16_reloc_p (r_type)) + if (hi16_reloc_p (r_type) + || got16_reloc_p (r_type) + || tls_hi16_reloc_p (r_type)) addend = mips_elf_high (addend); else if (r_type == R_MIPS_HIGHER) addend = mips_elf_higher (addend); diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp index 6fc960dfc10..e8a1d42791e 100644 --- a/ld/testsuite/ld-mips-elf/mips-elf.exp +++ b/ld/testsuite/ld-mips-elf/mips-elf.exp @@ -867,6 +867,16 @@ run_dump_test_n64 "pcrel-hilo-srec" \ [list [list name (n64)] \ [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]] +run_dump_test_o32 "pr19977" +run_dump_test_n32 "pr19977" [list [list name (n32)]] +run_dump_test_o32 "pr19977-mips16" noarch +run_dump_test_n32 "pr19977-mips16" [list noarch [list name (n32)]] +run_dump_test_o32 "pr19977-micromips" noarch +run_dump_test_n32 "pr19977-micromips" [list noarch [list name (n32)]] +run_dump_test_o32 "pr19977-r" +run_dump_test_o32 "pr19977-r-mips16" noarch +run_dump_test_o32 "pr19977-r-micromips" noarch + if { $linux_gnu } { run_dump_test_n32 "textrel-1" run_dump_test "got-page-1" diff --git a/ld/testsuite/ld-mips-elf/pr19977-micromips.d b/ld/testsuite/ld-mips-elf/pr19977-micromips.d new file mode 100644 index 00000000000..021b29c7f10 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pr19977-micromips.d @@ -0,0 +1,25 @@ +#name: pr19977 microMIPS +#source: ../../../gas/testsuite/gas/mips/pr19977.s +#as: -mmicromips -march=mips64r2 +#objdump: -d +#ld: -Tpr19977.ld -e 0 -N +#notarget: mips*el-ps2-elf* + +.*: file format elf.*mips.* + +Disassembly of section \.text: + +10000000 <[^>]*>: +10000000: 3060 1122 li v1,4386 +10000004: 0063 8000 sll v1,v1,0x10 +10000008: 3063 2988 addiu v1,v1,10632 +1000000c: 3060 1122 li v1,4386 +10000010: 0063 8000 sll v1,v1,0x10 +10000014: 3063 1988 addiu v1,v1,6536 +10000018: 3060 1122 li v1,4386 +1000001c: 0063 8000 sll v1,v1,0x10 +10000020: 3063 a988 addiu v1,v1,-22136 +10000024: 3060 1122 li v1,4386 +10000028: 0063 8000 sll v1,v1,0x10 +1000002c: 3063 9988 addiu v1,v1,-26232 +#pass diff --git a/ld/testsuite/ld-mips-elf/pr19977-mips16.d b/ld/testsuite/ld-mips-elf/pr19977-mips16.d new file mode 100644 index 00000000000..c927357c5ac --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pr19977-mips16.d @@ -0,0 +1,24 @@ +#name: pr19977 MIPS16 +#source: ../../../gas/testsuite/gas/mips/pr19977.s +#as: -mips16 -march=mips3 +#objdump: -d +#ld: -Tpr19977.ld -e 0 -N + +.*: file format elf.*mips.* + +Disassembly of section \.text: + +10000000 <[^>]*>: +10000000: f122 6b02 li v1,4386 +10000004: f400 3360 sll v1,16 +10000008: f185 4b08 addiu v1,10632 +1000000c: f122 6b02 li v1,4386 +10000010: f400 3360 sll v1,16 +10000014: f183 4b08 addiu v1,6536 +10000018: f122 6b02 li v1,4386 +1000001c: f400 3360 sll v1,16 +10000020: f195 4b08 addiu v1,-22136 +10000024: f122 6b02 li v1,4386 +10000028: f400 3360 sll v1,16 +1000002c: f193 4b08 addiu v1,-26232 +#pass diff --git a/ld/testsuite/ld-mips-elf/pr19977-r-micromips.d b/ld/testsuite/ld-mips-elf/pr19977-r-micromips.d new file mode 100644 index 00000000000..db99b97035a --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pr19977-r-micromips.d @@ -0,0 +1,8 @@ +#name: pr19977 microMIPS -r +#source: pr19977-r.s +#source: ../../../gas/testsuite/gas/mips/pr19977.s +#as: -mmicromips -march=mips64r2 +#objdump: -dr +#ld: -r +#notarget: mips*el-ps2-elf* +#dump: pr19977-r.d diff --git a/ld/testsuite/ld-mips-elf/pr19977-r-mips16.d b/ld/testsuite/ld-mips-elf/pr19977-r-mips16.d new file mode 100644 index 00000000000..dafa793248d --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pr19977-r-mips16.d @@ -0,0 +1,7 @@ +#name: pr19977 MIPS16 -r +#source: pr19977-r.s +#source: ../../../gas/testsuite/gas/mips/pr19977.s +#as: -mips16 -march=mips3 +#objdump: -dr +#ld: -r +#dump: pr19977-r.d diff --git a/ld/testsuite/ld-mips-elf/pr19977-r.d b/ld/testsuite/ld-mips-elf/pr19977-r.d new file mode 100644 index 00000000000..166194b199e --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pr19977-r.d @@ -0,0 +1,32 @@ +#name: pr19977 MIPS -r +#source: pr19977-r.s +#source: ../../../gas/testsuite/gas/mips/pr19977.s +#objdump: -dr +#ld: -r + +.* + +Disassembly of section \.text: + +0+ : + 0: .* li v1,4387 + 0: R_(|MICRO)MIPS(|16)_TLS_TPREL_HI16 \$loc0 + 4: .* sll .* + 8: .* addiu v1(|,v1),-26232 + 8: R_(|MICRO)MIPS(|16)_TLS_TPREL_LO16 \$loc0 + c: .* li v1,4387 + c: R_(|MICRO)MIPS(|16)_TLS_DTPREL_HI16 \$loc0 + 10: .* sll .* + 14: .* addiu v1(|,v1),-26232 + 14: R_(|MICRO)MIPS(|16)_TLS_DTPREL_LO16 \$loc0 + 18: .* li v1,4387 + 18: R_(|MICRO)MIPS(|16)_TLS_TPREL_HI16 \.tdata + 1c: .* sll .* + 20: .* addiu v1(|,v1),-30328 + 20: R_(|MICRO)MIPS(|16)_TLS_TPREL_LO16 \.tdata + 24: .* li v1,4387 + 24: R_(|MICRO)MIPS(|16)_TLS_DTPREL_HI16 \.tdata + 28: .* sll .* + 2c: .* addiu v1(|,v1),-30328 + 2c: R_(|MICRO)MIPS(|16)_TLS_DTPREL_LO16 \.tdata +#pass diff --git a/ld/testsuite/ld-mips-elf/pr19977-r.s b/ld/testsuite/ld-mips-elf/pr19977-r.s new file mode 100644 index 00000000000..4a46b306fb7 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pr19977-r.s @@ -0,0 +1,2 @@ + .section .tdata,"awT",%progbits + .space 28672 diff --git a/ld/testsuite/ld-mips-elf/pr19977.d b/ld/testsuite/ld-mips-elf/pr19977.d new file mode 100644 index 00000000000..145f69727b2 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pr19977.d @@ -0,0 +1,23 @@ +#name: pr19977 MIPS +#source: ../../../gas/testsuite/gas/mips/pr19977.s +#objdump: -d +#ld: -Tpr19977.ld -e 0 -N + +.*: file format elf.*mips.* + +Disassembly of section \.text: + +10000000 <[^>]*>: +10000000: 24031122 li v1,4386 +10000004: 00031c00 sll v1,v1,0x10 +10000008: 24632988 addiu v1,v1,10632 +1000000c: 24031122 li v1,4386 +10000010: 00031c00 sll v1,v1,0x10 +10000014: 24631988 addiu v1,v1,6536 +10000018: 24031122 li v1,4386 +1000001c: 00031c00 sll v1,v1,0x10 +10000020: 2463a988 addiu v1,v1,-22136 +10000024: 24031122 li v1,4386 +10000028: 00031c00 sll v1,v1,0x10 +1000002c: 24639988 addiu v1,v1,-26232 +#pass diff --git a/ld/testsuite/ld-mips-elf/pr19977.ld b/ld/testsuite/ld-mips-elf/pr19977.ld new file mode 100644 index 00000000000..0b2f7c12b50 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pr19977.ld @@ -0,0 +1,14 @@ +MEMORY +{ + text (rx) : ORIGIN = 0x10000000, LENGTH = 0x40000 + data (w) : ORIGIN = 0x34560000, LENGTH = 0x40000 +} +SECTIONS +{ + .text : { *(.text) } >text + .tdata : { *(.tdata) } >data + .symtab : { *(.symtab) } + .strtab : { *(.strtab) } + .shstrtab : { *(.shstrtab) } + /DISCARD/ : { *(*) } +} -- 2.47.2