aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/elfxx-mips.c64
-rw-r--r--ld/testsuite/ld-mips-elf/mips-elf.exp10
-rw-r--r--ld/testsuite/ld-mips-elf/pr19977-micromips.d25
-rw-r--r--ld/testsuite/ld-mips-elf/pr19977-mips16.d24
-rw-r--r--ld/testsuite/ld-mips-elf/pr19977-r-micromips.d8
-rw-r--r--ld/testsuite/ld-mips-elf/pr19977-r-mips16.d7
-rw-r--r--ld/testsuite/ld-mips-elf/pr19977-r.d32
-rw-r--r--ld/testsuite/ld-mips-elf/pr19977-r.s2
-rw-r--r--ld/testsuite/ld-mips-elf/pr19977.d23
-rw-r--r--ld/testsuite/ld-mips-elf/pr19977.ld14
10 files changed, 199 insertions, 10 deletions
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 7d1dff1..3c38f51 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -2294,6 +2294,17 @@ lo16_reloc_p (int r_type)
}
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)
{
return r_type == R_MIPS16_26 || r_type == R_MIPS16_CALL16;
@@ -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 6fc960d..e8a1d42 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 0000000..021b29c
--- /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 0000000..c927357
--- /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 0000000..db99b97
--- /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 0000000..dafa793
--- /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 0000000..166194b
--- /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+ <foo>:
+ 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 0000000..4a46b30
--- /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 0000000..145f697
--- /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 0000000..0b2f7c1
--- /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/ : { *(*) }
+}