summaryrefslogtreecommitdiff
path: root/ld/testsuite
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2020-04-01 14:31:47 -0700
committerH.J. Lu <hjl.tools@gmail.com>2020-04-01 14:31:47 -0700
commit382aae06322799a25ea52fe61b243cbca4db8d66 (patch)
treebc60e7b2d1d5acc2622c393933788146f8b1c291 /ld/testsuite
parent6b4a335bf7b7996e904e895b3fdc35443c40cfca (diff)
downloadbinutils-gdb-382aae06322799a25ea52fe61b243cbca4db8d66.tar.gz
x86: Only allow S + A relocations against absolute symbol
Since value of non-preemptible absolute symbol (SHN_ABS) won't change, only relocations, which can be resolved as absolute value + addend, and GOTPCREL relocations, where absolute value + addend is stored in the GOT slot, against non-preemptible absolute symbol are allowed in PIE and shared library. Also convert load relocation to R_386_32, R_X86_64_32S or R_X86_64_32 for relocation against non-preemptible absolute symbol. Don't convert to R_X86_64_32S nor R_X86_64_32 for non-preemptible absolute symbol if they overflow. bfd/ PR ld/25749 PR ld/25754 * elf32-i386.c (elf_i386_convert_load_reloc): Convert load relocation to R_386_32 for relocation against non-preemptible absolute symbol. (elf_i386_check_relocs): Call _bfd_elf_x86_valid_reloc_p. Don't allocate dynamic relocation for non-preemptible absolute symbol. (elf_i386_relocate_section): Pass sec to GENERATE_DYNAMIC_RELOCATION_P. * elf64-x86-64.c (R_X86_64_converted_reloc_bit): Moved. (elf_x86_64_convert_load_reloc): Covert load relocation to R_X86_64_32S or R_X86_64_32 for relocation against non-preemptible absolute symbol. Don't convert to R_X86_64_32S nor R_X86_64_32 for non-preemptible absolute symbol if they overflow. (elf_x86_64_check_relocs): Call _bfd_elf_x86_valid_reloc_p. Set tls_type for GOT slot to GOT_ABS for non-preemptible absolute symbol. Don't allocate dynamic relocation for non-preemptible absolute symbol. (elf_x86_64_relocate_section): Don't generate relative relocation for GOTPCREL relocations aganst local absolute symbol. Pass sec to GENERATE_DYNAMIC_RELOCATION_P. * elfxx-x86.c (elf_x86_allocate_dynrelocs): No dynamic relocation against non-preemptible absolute symbol. (_bfd_elf_x86_valid_reloc_p): New function. (_bfd_x86_elf_size_dynamic_sections): No dynamic relocation for GOT_ABS GOT slot. * elfxx-x86.h (GENERATE_DYNAMIC_RELOCATION_P): Add an SEC argument. Don't generate dynamic relocation against non-preemptible absolute symbol. (ABS_SYMBOL_P): New. (GENERATE_RELATIVE_RELOC_P): Don't generate relative relocation against non-preemptible absolute symbol. (GOT_ABS): New. (R_X86_64_converted_reloc_bit): New. Moved from elf64-x86-64.c. (_bfd_elf_x86_valid_reloc_p): New. ld/ PR ld/25749 PR ld/25754 * testsuite/ld-elf/linux-x86.exp: Run ld/25749 tests. * testsuite/ld-elf/pr25749-1.c: New file. * testsuite/ld-elf/pr25749-1a.c: Likewise. * testsuite/ld-elf/pr25749-1b.c: Likewise. * testsuite/ld-elf/pr25749-1b.err: Likewise. * testsuite/ld-elf/pr25749-1c.c: Likewise. * testsuite/ld-elf/pr25749-1d.c: Likewise. * testsuite/ld-elf/pr25749-2.c: Likewise. * testsuite/ld-elf/pr25749-2a.s: Likewise. * testsuite/ld-elf/pr25749-2b.s: Likewise. * testsuite/ld-elf/pr25749.rd: Likewise. * testsuite/ld-elf/pr25754-1a.c: Likewise. * testsuite/ld-elf/pr25754-1b.s: Likewise. * testsuite/ld-elf/pr25754-2a.c: Likewise. * testsuite/ld-elf/pr25754-2b.err: Likewise. * testsuite/ld-elf/pr25754-2b.s: Likewise. * testsuite/ld-elf/pr25754-3a.c: Likewise. * testsuite/ld-elf/pr25754-3b.s: Likewise. * testsuite/ld-elf/pr25754-4a.c: Likewise. * testsuite/ld-elf/pr25754-4b.s: Likewise. * testsuite/ld-elf/pr25754-4c.s: Likewise. * testsuite/ld-elf/pr25754-5a.c: Likewise. * testsuite/ld-elf/pr25754-5b.s: Likewise. * testsuite/ld-elf/pr25754-5c.s: Likewise. * testsuite/ld-elf/pr25754-6a.c: Likewise. * testsuite/ld-elf/pr25754-6b.s: Likewise. * testsuite/ld-x86-64/pr19609-6a.d: Don't expect linker error.
Diffstat (limited to 'ld/testsuite')
-rw-r--r--ld/testsuite/ld-elf/linux-x86.exp167
-rw-r--r--ld/testsuite/ld-elf/pr25749-1.c12
-rw-r--r--ld/testsuite/ld-elf/pr25749-1a.c11
-rw-r--r--ld/testsuite/ld-elf/pr25749-1b.c9
-rw-r--r--ld/testsuite/ld-elf/pr25749-1b.err3
-rw-r--r--ld/testsuite/ld-elf/pr25749-1c.c9
-rw-r--r--ld/testsuite/ld-elf/pr25749-1d.c19
-rw-r--r--ld/testsuite/ld-elf/pr25749-2.c12
-rw-r--r--ld/testsuite/ld-elf/pr25749-2a.s6
-rw-r--r--ld/testsuite/ld-elf/pr25749-2b.s7
-rw-r--r--ld/testsuite/ld-elf/pr25749.rd4
-rw-r--r--ld/testsuite/ld-elf/pr25754-1a.c19
-rw-r--r--ld/testsuite/ld-elf/pr25754-1b.s3
-rw-r--r--ld/testsuite/ld-elf/pr25754-2a.c20
-rw-r--r--ld/testsuite/ld-elf/pr25754-2b.s3
-rw-r--r--ld/testsuite/ld-elf/pr25754-3a.c19
-rw-r--r--ld/testsuite/ld-elf/pr25754-3b.s3
-rw-r--r--ld/testsuite/ld-elf/pr25754-4a.c12
-rw-r--r--ld/testsuite/ld-elf/pr25754-4b.s23
-rw-r--r--ld/testsuite/ld-elf/pr25754-4c.s12
-rw-r--r--ld/testsuite/ld-elf/pr25754-5a.c12
-rw-r--r--ld/testsuite/ld-elf/pr25754-5b.s23
-rw-r--r--ld/testsuite/ld-elf/pr25754-5c.s12
-rw-r--r--ld/testsuite/ld-elf/pr25754-6a.c12
-rw-r--r--ld/testsuite/ld-elf/pr25754-6b.s12
-rw-r--r--ld/testsuite/ld-x86-64/pr19609-6a.d11
26 files changed, 454 insertions, 1 deletions
diff --git a/ld/testsuite/ld-elf/linux-x86.exp b/ld/testsuite/ld-elf/linux-x86.exp
index 63a321b9668..7186dede711 100644
--- a/ld/testsuite/ld-elf/linux-x86.exp
+++ b/ld/testsuite/ld-elf/linux-x86.exp
@@ -115,3 +115,170 @@ elfedit_test "--disable-x86-feature shstk" x86-feature-1 x86-feature-1c
elfedit_test "--disable-x86-feature ibt" x86-feature-1 x86-feature-1d
elfedit_test "--enable-x86-feature ibt --enable-x86-feature shstk" \
x86-feature-1 x86-feature-1e
+
+proc check_pr25749a {testname srcfilea srcfileb cflags ldflags lderror} {
+ global objcopy
+ global srcdir
+ global subdir
+
+ if { [istarget "i?86-*-linux*"] } {
+ set output_arch "i386:i386"
+ set output_target "elf32-i386"
+ } else {
+ set output_arch "i386:x86-64"
+ if {[istarget "x86_64-*-linux*-gnux32"]} {
+ set output_target "elf32-x86-64"
+ } else {
+ set output_target "elf64-x86-64"
+ }
+ }
+
+ exec cp $srcdir/$subdir/$srcfilea $srcfilea
+ set pr25749_bin "$objcopy -B $output_arch -I binary -O $output_target $srcfilea tmpdir/pr25749-bin.o"
+ send_log "$pr25749_bin\n"
+ set got [remote_exec host "$pr25749_bin"]
+ if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+ send_log "$got\n"
+ fail "Convert $srcfilea to $output_target"
+ return
+ }
+
+ if {"$lderror" == ""} {
+ run_cc_link_tests [list \
+ [list \
+ "Build $testname ($ldflags $cflags)" \
+ "$ldflags tmpdir/pr25749-bin.o" \
+ "$cflags" \
+ [list $srcfilea $srcfileb]\
+ {{readelf {-Wr} pr25749.rd}} \
+ "${testname}a" \
+ ] \
+ ]
+ run_ld_link_exec_tests [list \
+ [list \
+ "Run ${testname}a ($ldflags $cflags)" \
+ "$ldflags tmpdir/pr25749-bin.o" \
+ "" \
+ [list $srcfilea $srcfileb]\
+ "${testname}a" \
+ "pass.out" \
+ "$cflags" \
+ ] \
+ ]
+ } else {
+ run_cc_link_tests [list \
+ [list \
+ "Build $testname ($ldflags $cflags)" \
+ "$ldflags tmpdir/pr25749-bin.o" \
+ "$cflags" \
+ [list $srcfilea $srcfileb]\
+ [list [list error_output $lderror]] \
+ "$testname" \
+ ] \
+ ]
+ }
+}
+
+check_pr25749a "pr25749-1a" "pr25749-1.c" "pr25749-1a.c" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749a "pr25749-1a" "pr25749-1.c" "pr25749-1a.c" "-fPIE" "-pie" ""
+check_pr25749a "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+if { [istarget "i?86-*-linux*"] } {
+ check_pr25749a "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "-fPIE" "-pie" ""
+} else {
+ check_pr25749a "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "-fPIE" "-pie" "pr25749-1b.err"
+}
+check_pr25749a "pr25749-1c" "pr25749-1.c" "pr25749-1c.c" "-fPIC" "-shared" "pr25749-1b.err"
+check_pr25749a "pr25749-2a" "pr25749-2.c" "pr25749-2a.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749a "pr25749-2a" "pr25749-2.c" "pr25749-2a.s" "-fPIE" "-pie" ""
+check_pr25749a "pr25749-2b" "pr25749-2.c" "pr25749-2b.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749a "pr25749-2b" "pr25749-2.c" "pr25749-2b.s" "-fPIE" "-pie" ""
+check_pr25749a "pr25754-1a" "pr25754-1a.c" "pr25754-1b.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749a "pr25754-1b" "pr25754-1a.c" "pr25754-1b.s" "-fPIE" "$NOPIE_LDFLAGS" ""
+check_pr25749a "pr25754-1c" "pr25754-1a.c" "pr25754-1b.s" "-fPIC" "$NOPIE_LDFLAGS" ""
+check_pr25749a "pr25754-1d" "pr25754-1a.c" "pr25754-1b.s" "-fPIC" "-pie" ""
+if { [istarget "i?86-*-linux*"] || [istarget "x86_64-*-linux*-gnux32"]} {
+ check_pr25749a "pr25754-2a" "pr25754-2a.c" "pr25754-2b.s" "-fPIC" "$NOPIE_LDFLAGS" ""
+ check_pr25749a "pr25754-2b" "pr25754-2a.c" "pr25754-2b.s" "-fPIC" "-pie" ""
+} else {
+ check_pr25749a "pr25754-3a" "pr25754-3a.c" "pr25754-3b.s" "-fPIC" "$NOPIE_LDFLAGS" ""
+ check_pr25749a "pr25754-3b" "pr25754-3a.c" "pr25754-3b.s" "-fPIC" "-pie" ""
+}
+if { [istarget "i?86-*-linux*"] } {
+ check_pr25749a "pr25754-4a" "pr25754-4a.c" "pr25754-4b.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+ check_pr25749a "pr25754-4b" "pr25754-4a.c" "pr25754-4b.s" "-fpie" "-pie" ""
+ check_pr25749a "pr25754-5a" "pr25754-5a.c" "pr25754-5b.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+ check_pr25749a "pr25754-5b" "pr25754-5a.c" "pr25754-5b.s" "-fpie" "-pie" ""
+} else {
+ check_pr25749a "pr25754-4a" "pr25754-4a.c" "pr25754-4c.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+ check_pr25749a "pr25754-4b" "pr25754-4a.c" "pr25754-4c.s" "-fpie" "-pie" ""
+ check_pr25749a "pr25754-5a" "pr25754-5a.c" "pr25754-5c.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+ check_pr25749a "pr25754-5b" "pr25754-5a.c" "pr25754-5c.s" "-fpie" "-pie" ""
+ if { ![istarget "x86_64-*-linux*-gnux32"]} {
+ check_pr25749a "pr25754-6a" "pr25754-6a.c" "pr25754-6b.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+ check_pr25749a "pr25754-6b" "pr25754-6a.c" "pr25754-6b.s" "-fpie" "-pie" ""
+ }
+}
+
+proc check_pr25749b {testname srcfilea srcfileb cflags ldflags dsoldflags} {
+ global objcopy
+ global srcdir
+ global subdir
+
+ if { [istarget "i?86-*-linux*"] } {
+ set output_arch "i386:i386"
+ set output_target "elf32-i386"
+ } else {
+ set output_arch "i386:x86-64"
+ if {[istarget "x86_64-*-linux*-gnux32"]} {
+ set output_target "elf32-x86-64"
+ } else {
+ set output_target "elf64-x86-64"
+ }
+ }
+
+ exec cp $srcdir/$subdir/$srcfilea $srcfilea
+ set pr25749_bin "$objcopy -B $output_arch -I binary -O $output_target $srcfilea tmpdir/pr25749-bin.o"
+ send_log "$pr25749_bin\n"
+ set got [remote_exec host "$pr25749_bin"]
+ if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+ send_log "$got\n"
+ fail "Convert $srcfilea to $output_target"
+ return
+ }
+
+ run_cc_link_tests [list \
+ [list \
+ "Build lib${testname}.so ($dsoldflags)" \
+ "-shared $dsoldflags tmpdir/pr25749-bin.o" \
+ "-fPIC" \
+ [list $srcfileb] \
+ {{readelf {-Wr} pr25749.rd}} \
+ "lib${testname}.so" \
+ ] \
+ ]
+ run_ld_link_exec_tests [list \
+ [list \
+ "Run ${testname}b ($ldflags $cflags)" \
+ "$ldflags -Wl,--no-as-needed tmpdir/lib${testname}.so" \
+ "" \
+ [list $srcfilea]\
+ "${testname}b" \
+ "pass.out" \
+ "$cflags" \
+ ] \
+ ]
+}
+
+check_pr25749b "pr25749-1a" "pr25749-1.c" "pr25749-1a.c" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749b "pr25749-1a" "pr25749-1.c" "pr25749-1a.c" "-fPIE" "-pie" ""
+check_pr25749b "pr25749-1a" "pr25749-1.c" "pr25749-1a.c" "-fPIE" "-pie" "-Wl,-Bsymbolic"
+check_pr25749b "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749b "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "-fPIE" "-pie" ""
+check_pr25749b "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "-fPIE" "-pie" "-Wl,-Bsymbolic"
+check_pr25749b "pr25749-1d" "pr25749-1.c" "pr25749-1d.c" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "-Wl,-defsym=_begin=0"
+check_pr25749b "pr25749-1d" "pr25749-1.c" "pr25749-1d.c" "-fPIE" "-pie" "-Wl,-defsym=_begin=0"
+check_pr25749b "pr25749-1d" "pr25749-1.c" "pr25749-1d.c" "-fPIE" "-pie" "-Wl,-Bsymbolic -Wl,-defsym=_begin=0"
+check_pr25749b "pr25749-2a" "pr25749-2.c" "pr25749-2a.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749b "pr25749-2a" "pr25749-2.c" "pr25749-2a.s" "-fPIE" "-pie" ""
+check_pr25749b "pr25749-2b" "pr25749-2.c" "pr25749-2b.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749b "pr25749-2b" "pr25749-2.c" "pr25749-2b.s" "-fPIE" "-pie" ""
diff --git a/ld/testsuite/ld-elf/pr25749-1.c b/ld/testsuite/ld-elf/pr25749-1.c
new file mode 100644
index 00000000000..5b37af08c69
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-1.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <bfd_stdint.h>
+
+extern intptr_t size (void);
+
+int
+main ()
+{
+ if (size () == 147)
+ printf ("PASS\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/pr25749-1a.c b/ld/testsuite/ld-elf/pr25749-1a.c
new file mode 100644
index 00000000000..775623b8c9c
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-1a.c
@@ -0,0 +1,11 @@
+#include <bfd_stdint.h>
+
+extern void *_binary_pr25749_1_c_start;
+extern void *_binary_pr25749_1_c_end;
+
+intptr_t
+size (void)
+{
+ return ((intptr_t) &_binary_pr25749_1_c_end
+ - (intptr_t) &_binary_pr25749_1_c_start);
+}
diff --git a/ld/testsuite/ld-elf/pr25749-1b.c b/ld/testsuite/ld-elf/pr25749-1b.c
new file mode 100644
index 00000000000..f02a4087004
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-1b.c
@@ -0,0 +1,9 @@
+#include <bfd_stdint.h>
+
+extern void *_binary_pr25749_1_c_size;
+
+intptr_t
+size (void)
+{
+ return (intptr_t) &_binary_pr25749_1_c_size;
+}
diff --git a/ld/testsuite/ld-elf/pr25749-1b.err b/ld/testsuite/ld-elf/pr25749-1b.err
new file mode 100644
index 00000000000..bb389172f16
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-1b.err
@@ -0,0 +1,3 @@
+#...
+.*: .* against absolute symbol `_binary_pr25749_1_c_size' .* is disallowed
+#pass
diff --git a/ld/testsuite/ld-elf/pr25749-1c.c b/ld/testsuite/ld-elf/pr25749-1c.c
new file mode 100644
index 00000000000..f2847d7f623
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-1c.c
@@ -0,0 +1,9 @@
+#include <bfd_stdint.h>
+
+extern void *_binary_pr25749_1_c_size __attribute__ ((visibility("hidden")));
+
+intptr_t
+size (void)
+{
+ return (intptr_t) &_binary_pr25749_1_c_size;
+}
diff --git a/ld/testsuite/ld-elf/pr25749-1d.c b/ld/testsuite/ld-elf/pr25749-1d.c
new file mode 100644
index 00000000000..33b869deb5d
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-1d.c
@@ -0,0 +1,19 @@
+#include <bfd_stdint.h>
+
+extern void *_binary_pr25749_1_c_start;
+extern void *_binary_pr25749_1_c_end;
+
+intptr_t
+size (void)
+{
+ return ((intptr_t) &_binary_pr25749_1_c_end
+ - (intptr_t) &_binary_pr25749_1_c_start);
+}
+
+extern void *_begin __attribute__ ((visibility("hidden")));
+
+intptr_t
+size_p (void)
+{
+ return (intptr_t) &_begin;
+}
diff --git a/ld/testsuite/ld-elf/pr25749-2.c b/ld/testsuite/ld-elf/pr25749-2.c
new file mode 100644
index 00000000000..820bebc1673
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-2.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <bfd_stdint.h>
+
+extern intptr_t size;
+
+int
+main ()
+{
+ if (size == 137)
+ printf ("PASS\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/pr25749-2a.s b/ld/testsuite/ld-elf/pr25749-2a.s
new file mode 100644
index 00000000000..df486fe3294
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-2a.s
@@ -0,0 +1,6 @@
+ .data
+ .globl size
+ .type size, %object
+size:
+ .dc.a _binary_pr25749_2_c_size
+ .size size, .-size
diff --git a/ld/testsuite/ld-elf/pr25749-2b.s b/ld/testsuite/ld-elf/pr25749-2b.s
new file mode 100644
index 00000000000..ba82c450bc2
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-2b.s
@@ -0,0 +1,7 @@
+ .data
+ .hidden _binary_pr25749_2_c_size
+ .globl size
+ .type size, %object
+size:
+ .dc.a _binary_pr25749_2_c_size
+ .size size, .-size
diff --git a/ld/testsuite/ld-elf/pr25749.rd b/ld/testsuite/ld-elf/pr25749.rd
new file mode 100644
index 00000000000..fbc68bf2688
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749.rd
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f ]+R_.*_NONE.*
+#...
diff --git a/ld/testsuite/ld-elf/pr25754-1a.c b/ld/testsuite/ld-elf/pr25754-1a.c
new file mode 100644
index 00000000000..2b048ec09bb
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-1a.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <bfd_stdint.h>
+
+extern uintptr_t bar;
+
+uintptr_t *
+__attribute__ ((noinline, noclone))
+get_bar (void)
+{
+ return &bar;
+}
+
+int
+main ()
+{
+ if ((uintptr_t) get_bar () == 42)
+ printf ("PASS\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/pr25754-1b.s b/ld/testsuite/ld-elf/pr25754-1b.s
new file mode 100644
index 00000000000..99d585d6b5f
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-1b.s
@@ -0,0 +1,3 @@
+ .data
+ .global bar
+ bar = 42
diff --git a/ld/testsuite/ld-elf/pr25754-2a.c b/ld/testsuite/ld-elf/pr25754-2a.c
new file mode 100644
index 00000000000..7c9f58116e7
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-2a.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <bfd_stdint.h>
+
+extern uintptr_t bar;
+
+uintptr_t *
+__attribute__ ((noinline, noclone))
+get_bar (void)
+{
+ return &bar;
+}
+
+int
+main ()
+{
+ if ((uintptr_t) get_bar () == 0xfffffff0U)
+ printf ("PASS\n");
+ return 0;
+}
+#include <stdio.h>
diff --git a/ld/testsuite/ld-elf/pr25754-2b.s b/ld/testsuite/ld-elf/pr25754-2b.s
new file mode 100644
index 00000000000..9cab99303ee
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-2b.s
@@ -0,0 +1,3 @@
+ .data
+ .global bar
+ bar = 0xfffffff0
diff --git a/ld/testsuite/ld-elf/pr25754-3a.c b/ld/testsuite/ld-elf/pr25754-3a.c
new file mode 100644
index 00000000000..2d4f02abe5a
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-3a.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <bfd_stdint.h>
+
+extern uintptr_t bar;
+
+uintptr_t *
+__attribute__ ((noinline, noclone))
+get_bar (void)
+{
+ return &bar;
+}
+
+int
+main ()
+{
+ if ((uintptr_t) get_bar () == -0x80000001LL)
+ printf ("PASS\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/pr25754-3b.s b/ld/testsuite/ld-elf/pr25754-3b.s
new file mode 100644
index 00000000000..aad3e45e0f6
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-3b.s
@@ -0,0 +1,3 @@
+ .data
+ .global bar
+ bar = -0x80000001
diff --git a/ld/testsuite/ld-elf/pr25754-4a.c b/ld/testsuite/ld-elf/pr25754-4a.c
new file mode 100644
index 00000000000..e2c2f8d54d0
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-4a.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <bfd_stdint.h>
+
+extern uintptr_t *get_bar (void);
+
+int
+main ()
+{
+ if ((uintptr_t) get_bar () == 0x7fffffffULL)
+ printf ("PASS\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/pr25754-4b.s b/ld/testsuite/ld-elf/pr25754-4b.s
new file mode 100644
index 00000000000..448406dff89
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-4b.s
@@ -0,0 +1,23 @@
+ .text
+ .p2align 4
+ .globl get_bar
+ .type get_bar, @function
+get_bar:
+ .cfi_startproc
+ call __x86.get_pc_thunk.ax
+ addl $_GLOBAL_OFFSET_TABLE_, %eax
+ movl bar@GOT(%eax), %eax
+ ret
+ .cfi_endproc
+ .size get_bar, .-get_bar
+ bar = 0x7fffffff
+ .section .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
+ .globl __x86.get_pc_thunk.ax
+ .hidden __x86.get_pc_thunk.ax
+ .type __x86.get_pc_thunk.ax, @function
+__x86.get_pc_thunk.ax:
+ .cfi_startproc
+ movl (%esp), %eax
+ ret
+ .cfi_endproc
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-elf/pr25754-4c.s b/ld/testsuite/ld-elf/pr25754-4c.s
new file mode 100644
index 00000000000..de450fe081e
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-4c.s
@@ -0,0 +1,12 @@
+ .text
+ .p2align 4
+ .globl get_bar
+ .type get_bar, @function
+get_bar:
+ .cfi_startproc
+ movq bar@GOTPCREL(%rip), %rax
+ ret
+ .cfi_endproc
+ .size get_bar, .-get_bar
+ bar = 0x7fffffff
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-elf/pr25754-5a.c b/ld/testsuite/ld-elf/pr25754-5a.c
new file mode 100644
index 00000000000..cb791dd56f7
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-5a.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <bfd_stdint.h>
+
+extern uintptr_t *get_bar (void);
+
+int
+main ()
+{
+ if ((uintptr_t) get_bar () == 0xfffffff0ULL)
+ printf ("PASS\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/pr25754-5b.s b/ld/testsuite/ld-elf/pr25754-5b.s
new file mode 100644
index 00000000000..2923c32ee9f
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-5b.s
@@ -0,0 +1,23 @@
+ .text
+ .p2align 4
+ .globl get_bar
+ .type get_bar, @function
+get_bar:
+ .cfi_startproc
+ call __x86.get_pc_thunk.ax
+ addl $_GLOBAL_OFFSET_TABLE_, %eax
+ movl bar@GOT(%eax), %eax
+ ret
+ .cfi_endproc
+ .size get_bar, .-get_bar
+ bar = 0xfffffff0
+ .section .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
+ .globl __x86.get_pc_thunk.ax
+ .hidden __x86.get_pc_thunk.ax
+ .type __x86.get_pc_thunk.ax, @function
+__x86.get_pc_thunk.ax:
+ .cfi_startproc
+ movl (%esp), %eax
+ ret
+ .cfi_endproc
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-elf/pr25754-5c.s b/ld/testsuite/ld-elf/pr25754-5c.s
new file mode 100644
index 00000000000..0195f19165d
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-5c.s
@@ -0,0 +1,12 @@
+ .text
+ .p2align 4
+ .globl get_bar
+ .type get_bar, @function
+get_bar:
+ .cfi_startproc
+ movq bar@GOTPCREL(%rip), %rax
+ ret
+ .cfi_endproc
+ .size get_bar, .-get_bar
+ bar = 0xfffffff0
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-elf/pr25754-6a.c b/ld/testsuite/ld-elf/pr25754-6a.c
new file mode 100644
index 00000000000..59633a3b4dd
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-6a.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <bfd_stdint.h>
+
+extern uintptr_t *get_bar (void);
+
+int
+main ()
+{
+ if ((uintptr_t) get_bar () == 0xffffffffffffff0ULL)
+ printf ("PASS\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/pr25754-6b.s b/ld/testsuite/ld-elf/pr25754-6b.s
new file mode 100644
index 00000000000..2532480e5f0
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-6b.s
@@ -0,0 +1,12 @@
+ .text
+ .p2align 4
+ .globl get_bar
+ .type get_bar, @function
+get_bar:
+ .cfi_startproc
+ movq bar@GOTPCREL(%rip), %rax
+ ret
+ .cfi_endproc
+ .size get_bar, .-get_bar
+ bar = 0xffffffffffffff0
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr19609-6a.d b/ld/testsuite/ld-x86-64/pr19609-6a.d
index 3c011d9b057..b340287f48b 100644
--- a/ld/testsuite/ld-x86-64/pr19609-6a.d
+++ b/ld/testsuite/ld-x86-64/pr19609-6a.d
@@ -1,4 +1,13 @@
#source: pr19609-6.s
#as: --64 -mrelax-relocations=yes
#ld: -melf_x86_64 --defsym foobar=0x80000000
-#error: failed to convert GOTPCREL relocation; relink with --no-relax
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <.got>
+#pass