* [PATCH] x86: Only allow S - A relocations against absolute symbol
@ 2020-03-31 4:43 H.J. Lu
2020-03-31 6:17 ` Fangrui Song
0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2020-03-31 4:43 UTC (permalink / raw)
To: binutils
Since value of non-preemptible absolute symbol (SHN_ABS) won't change,
only S - A relocations against non-preemptible absolute symbol are
allowed in PIE and shared library.
bfd/
PR ld/25749
* elf32-i386.c )elf_i386_relocate_section): Call
_bfd_elf_x86_valid_reloc_p. Pass sec to
GENERATE_DYNAMIC_RELOCATION_P.
* elf64-x86-64.c (elf_x86_64_relocate_section): Likewise.
* elfxx-x86.c (_bfd_elf_x86_valid_reloc_p): New function.
* elfxx-x86.h (GENERATE_DYNAMIC_RELOCATION_P): Add an SEC
argument. Don't generate dynamic relocation for relocation
against SHN_ABS symbol.
(_bfd_elf_x86_valid_reloc_p): New.
ld/
PR ld/25749
* 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-2.c: Likewise.
* testsuite/ld-elf/pr25749-2a.s: Likewise.
* testsuite/ld-elf/pr25749-2b.s: Likewise.
---
bfd/elf32-i386.c | 6 +-
bfd/elf64-x86-64.c | 6 +-
bfd/elfxx-x86.c | 53 +++++++++++
bfd/elfxx-x86.h | 8 +-
ld/testsuite/ld-elf/linux-x86.exp | 135 +++++++++++++++++++++++++++++
ld/testsuite/ld-elf/pr25749-1.c | 12 +++
ld/testsuite/ld-elf/pr25749-1a.c | 11 +++
ld/testsuite/ld-elf/pr25749-1b.c | 9 ++
ld/testsuite/ld-elf/pr25749-1b.err | 3 +
ld/testsuite/ld-elf/pr25749-1c.c | 9 ++
ld/testsuite/ld-elf/pr25749-2.c | 12 +++
ld/testsuite/ld-elf/pr25749-2a.s | 6 ++
ld/testsuite/ld-elf/pr25749-2b.s | 7 ++
13 files changed, 274 insertions(+), 3 deletions(-)
create mode 100644 ld/testsuite/ld-elf/pr25749-1.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1a.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1b.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1b.err
create mode 100644 ld/testsuite/ld-elf/pr25749-1c.c
create mode 100644 ld/testsuite/ld-elf/pr25749-2.c
create mode 100644 ld/testsuite/ld-elf/pr25749-2a.s
create mode 100644 ld/testsuite/ld-elf/pr25749-2b.s
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index eb7e1f8b34..c0998d3212 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -2212,6 +2212,10 @@ elf_i386_relocate_section (bfd *output_bfd,
continue;
}
+ if (!_bfd_elf_x86_valid_reloc_p (input_section, info, rel, sec,
+ h, sym, symtab_hdr, howto))
+ return FALSE;
+
eh = (struct elf_x86_link_hash_entry *) h;
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle
@@ -2704,7 +2708,7 @@ elf_i386_relocate_section (bfd *output_bfd,
|| is_vxworks_tls)
break;
- if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type,
+ if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, sec,
FALSE, resolved_to_zero,
(r_type == R_386_PC32)))
{
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 90e2702334..e3e6378741 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -2530,6 +2530,10 @@ elf_x86_64_relocate_section (bfd *output_bfd,
continue;
}
+ if (!_bfd_elf_x86_valid_reloc_p (input_section, info, rel, sec,
+ h, sym, symtab_hdr, howto))
+ return FALSE;
+
if (rel->r_addend == 0 && !ABI_64_P (output_bfd))
{
if (r_type == R_X86_64_64)
@@ -3175,7 +3179,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
&& (X86_PCREL_TYPE_P (r_type)
|| X86_SIZE_TYPE_P (r_type)));
- if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type,
+ if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, sec,
need_copy_reloc_in_pie,
resolved_to_zero, FALSE))
{
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 108e04a158..64e8170244 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -952,6 +952,59 @@ _bfd_x86_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
return _bfd_elf_link_check_relocs (abfd, info);
}
+bfd_boolean
+_bfd_elf_x86_valid_reloc_p (asection *input_section,
+ struct bfd_link_info *info,
+ const Elf_Internal_Rela *rel,
+ asection *sec,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym,
+ Elf_Internal_Shdr *symtab_hdr,
+ const reloc_howto_type *howto)
+{
+ bfd_boolean valid_p = TRUE;
+
+ /* Check If relocation against absolute symbol is valid in PIC. */
+ if (bfd_link_pic (info)
+ && bfd_is_abs_section (sec)
+ && (h == NULL || SYMBOL_REFERENCES_LOCAL_P (info, h)))
+ {
+ const struct elf_backend_data *bed
+ = get_elf_backend_data (input_section->owner);
+ unsigned int r_type = ELF32_R_TYPE (rel->r_info);
+
+ /* Only allow S - A relocations against absolute symbol. */
+ if (bed->target_id == X86_64_ELF_DATA)
+ valid_p = (r_type == R_X86_64_64
+ || r_type == R_X86_64_32
+ || r_type == R_X86_64_16
+ || r_type == R_X86_64_8);
+ else
+ valid_p = (r_type == R_386_32
+ || r_type == R_386_16
+ || r_type == R_386_8);
+
+ if (!valid_p)
+ {
+ const char *name;
+ if (h)
+ name = h->root.root.string;
+ else
+ name = bfd_elf_sym_name (input_section->owner, symtab_hdr,
+ sym, NULL);
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: in relocation %s against absolute symbol `%s' "
+ "at %#" PRIx64 " in section `%pA' is disallowed"),
+ input_section->owner, howto->name, name,
+ (uint64_t) rel->r_offset, input_section);
+ bfd_set_error (bfd_error_bad_value);
+ }
+ }
+
+ return valid_p;
+}
+
/* Set the sizes of the dynamic sections. */
bfd_boolean
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index bef17dc2ba..8a2731a194 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -120,10 +120,11 @@
relocations against resolved undefined weak symbols in PIE, except
when PC32_RELOC is TRUE. Undefined weak symbol is bound locally
when PIC is false. */
-#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, \
+#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, SEC, \
NEED_COPY_RELOC_IN_PIE, \
RESOLVED_TO_ZERO, PC32_RELOC) \
((bfd_link_pic (INFO) \
+ && !bfd_is_abs_section (SEC) \
&& !(NEED_COPY_RELOC_IN_PIE) \
&& ((EH) == NULL \
|| ((ELF_ST_VISIBILITY ((EH)->elf.other) == STV_DEFAULT \
@@ -652,6 +653,11 @@ extern int _bfd_x86_elf_compare_relocs
extern bfd_boolean _bfd_x86_elf_link_check_relocs
(bfd *, struct bfd_link_info *);
+extern bfd_boolean _bfd_elf_x86_valid_reloc_p
+ (asection *, struct bfd_link_info *, const Elf_Internal_Rela *,
+ asection *, struct elf_link_hash_entry *, Elf_Internal_Sym *,
+ Elf_Internal_Shdr *, const reloc_howto_type *);
+
extern bfd_boolean _bfd_x86_elf_size_dynamic_sections
(bfd *, struct bfd_link_info *);
diff --git a/ld/testsuite/ld-elf/linux-x86.exp b/ld/testsuite/ld-elf/linux-x86.exp
index 63a321b966..f34158d0b5 100644
--- a/ld/testsuite/ld-elf/linux-x86.exp
+++ b/ld/testsuite/ld-elf/linux-x86.exp
@@ -115,3 +115,138 @@ 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_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" ""
+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" ""
+
+proc check_pr25749b {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 lib${testname}.so ($ldflags $cflags)" \
+ "-shared tmpdir/pr25749-bin.o" \
+ "-fPIC" \
+ [list $srcfileb] \
+ "" \
+ "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" \
+ ] \
+ ]
+ } 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_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-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-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 0000000000..5b37af08c6
--- /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 0000000000..775623b8c9
--- /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 0000000000..f02a408700
--- /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 0000000000..bb389172f1
--- /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 0000000000..f2847d7f62
--- /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-2.c b/ld/testsuite/ld-elf/pr25749-2.c
new file mode 100644
index 0000000000..820bebc167
--- /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 0000000000..df486fe329
--- /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 0000000000..ba82c450bc
--- /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
--
2.25.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] x86: Only allow S - A relocations against absolute symbol
2020-03-31 4:43 [PATCH] x86: Only allow S - A relocations against absolute symbol H.J. Lu
@ 2020-03-31 6:17 ` Fangrui Song
2020-03-31 14:31 ` H.J. Lu
0 siblings, 1 reply; 10+ messages in thread
From: Fangrui Song @ 2020-03-31 6:17 UTC (permalink / raw)
To: H.J. Lu via Binutils
On 2020-03-30, H.J. Lu via Binutils wrote:
>Since value of non-preemptible absolute symbol (SHN_ABS) won't change,
>only S - A relocations against non-preemptible absolute symbol are
>allowed in PIE and shared library.
Thanks for the patch. At some point we should define some generic
relocation categories (https://reviews.llvm.org/rL266158). For example,
- R_ABS: R_X86_64_8, R_X86_64_16, R_X86_64_32, R_X86_64_64
R_AARCH64_ABS16, R_AARCH64_ABS32, R_AARCH64_ABS64
R_PPC64_ADDR16, R_PPC64_ADDR16_DS, R_PPC64_ADDR16_HA, ...
- R_PCREL: R_X86_64_PC8, R_X86_64_PC16, R_X86_64_PC32, R_X86_64_PC64
R_AARCH64_PREL16, R_AARCH64_PREL32, R_AARCH64_PREL64
- R_PLT_PCREL: R_X86_64_PLT32, R_AARCH64_CALL26
- R_GOT_PCREL: R_X86_64_GOTPCREL, R_X86_64_GOTPCRELX
Define a property is_preemptible as a more appropriate level of
abstraction for GENERATE_DYNAMIC_RELOCATION_P and some use cases of bfd_link_pic and bfd_link_executable...
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] x86: Only allow S - A relocations against absolute symbol
2020-03-31 6:17 ` Fangrui Song
@ 2020-03-31 14:31 ` H.J. Lu
2020-03-31 23:25 ` V3 " H.J. Lu
0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2020-03-31 14:31 UTC (permalink / raw)
To: Fangrui Song; +Cc: H.J. Lu via Binutils
[-- Attachment #1: Type: text/plain, Size: 1294 bytes --]
On Mon, Mar 30, 2020 at 11:18 PM Fangrui Song <i@maskray.me> wrote:
>
> On 2020-03-30, H.J. Lu via Binutils wrote:
> >Since value of non-preemptible absolute symbol (SHN_ABS) won't change,
> >only S - A relocations against non-preemptible absolute symbol are
> >allowed in PIE and shared library.
>
> Thanks for the patch. At some point we should define some generic
> relocation categories (https://reviews.llvm.org/rL266158). For example,
>
> - R_ABS: R_X86_64_8, R_X86_64_16, R_X86_64_32, R_X86_64_64
> R_AARCH64_ABS16, R_AARCH64_ABS32, R_AARCH64_ABS64
> R_PPC64_ADDR16, R_PPC64_ADDR16_DS, R_PPC64_ADDR16_HA, ...
> - R_PCREL: R_X86_64_PC8, R_X86_64_PC16, R_X86_64_PC32, R_X86_64_PC64
> R_AARCH64_PREL16, R_AARCH64_PREL32, R_AARCH64_PREL64
> - R_PLT_PCREL: R_X86_64_PLT32, R_AARCH64_CALL26
> - R_GOT_PCREL: R_X86_64_GOTPCREL, R_X86_64_GOTPCRELX
>
> Define a property is_preemptible as a more appropriate level of
> abstraction for GENERATE_DYNAMIC_RELOCATION_P and some use cases of bfd_link_pic and bfd_link_executable...
Current BFD linker delegates most, if not all, of relocation to each backend.
There are many similar codes in backends. I am sharing as much codes
between i386 and x86-64 backends as I can.
This is the patch I am checking in.
--
H.J.
[-- Attachment #2: 0001-x86-Only-allow-S-A-relocations-against-absolute-symb.patch --]
[-- Type: text/x-patch, Size: 17690 bytes --]
From c36ea2097c877e316bd278fdb076bc2ba883cba9 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 30 Mar 2020 18:36:39 -0700
Subject: [PATCH] x86: Only allow S + A relocations against absolute symbol
Since value of non-preemptible absolute symbol (SHN_ABS) won't change,
only relocations against non-preemptible absolute symbol, which can be
resolved as absolute value + addend, are allowed in PIE and shared
library.
bfd/
PR ld/25749
* elf32-i386.c (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 (elf_x86_64_check_relocs): Call
_bfd_elf_x86_valid_reloc_p. Don't allocate dynamic relocation
for non-preemptible absolute symbol.
(elf_x86_64_relocate_section): Pass sec to
GENERATE_DYNAMIC_RELOCATION_P.
* elfxx-x86.c (_bfd_elf_x86_valid_reloc_p): New function.
* elfxx-x86.h (GENERATE_DYNAMIC_RELOCATION_P): Add an SEC
argument. Don't generate dynamic relocation against
non-preemptible absolute symbol.
(_bfd_elf_x86_valid_reloc_p): New.
ld/
PR ld/25749
* 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-2.c: Likewise.
* testsuite/ld-elf/pr25749-2a.s: Likewise.
* testsuite/ld-elf/pr25749-2b.s: Likewise.
* testsuite/ld-elf/pr25749.rd: Likewise.
---
bfd/elf32-i386.c | 12 ++-
bfd/elf64-x86-64.c | 12 ++-
bfd/elfxx-x86.c | 77 +++++++++++++++++
bfd/elfxx-x86.h | 13 ++-
ld/testsuite/ld-elf/linux-x86.exp | 133 +++++++++++++++++++++++++++++
ld/testsuite/ld-elf/pr25749-1.c | 12 +++
ld/testsuite/ld-elf/pr25749-1a.c | 11 +++
ld/testsuite/ld-elf/pr25749-1b.c | 9 ++
ld/testsuite/ld-elf/pr25749-1b.err | 3 +
ld/testsuite/ld-elf/pr25749-1c.c | 9 ++
ld/testsuite/ld-elf/pr25749-2.c | 12 +++
ld/testsuite/ld-elf/pr25749-2a.s | 6 ++
ld/testsuite/ld-elf/pr25749-2b.s | 7 ++
ld/testsuite/ld-elf/pr25749.rd | 4 +
14 files changed, 312 insertions(+), 8 deletions(-)
create mode 100644 ld/testsuite/ld-elf/pr25749-1.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1a.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1b.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1b.err
create mode 100644 ld/testsuite/ld-elf/pr25749-1c.c
create mode 100644 ld/testsuite/ld-elf/pr25749-2.c
create mode 100644 ld/testsuite/ld-elf/pr25749-2a.s
create mode 100644 ld/testsuite/ld-elf/pr25749-2b.s
create mode 100644 ld/testsuite/ld-elf/pr25749.rd
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index eb7e1f8b34..03cc437d36 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1519,6 +1519,7 @@ elf_i386_check_relocs (bfd *abfd,
Elf_Internal_Sym *isym;
const char *name;
bfd_boolean size_reloc;
+ bfd_boolean no_dynreloc;
r_symndx = ELF32_R_SYM (rel->r_info);
r_type = ELF32_R_TYPE (rel->r_info);
@@ -1567,6 +1568,10 @@ elf_i386_check_relocs (bfd *abfd,
h = (struct elf_link_hash_entry *) h->root.u.i.link;
}
+ if (!_bfd_elf_x86_valid_reloc_p (sec, info, rel, h, isym,
+ symtab_hdr, &no_dynreloc))
+ return FALSE;
+
eh = (struct elf_x86_link_hash_entry *) h;
if (h != NULL)
{
@@ -1827,8 +1832,9 @@ elf_i386_check_relocs (bfd *abfd,
size_reloc = FALSE;
do_size:
- if (NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type,
- R_386_32))
+ if (!no_dynreloc
+ && NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type,
+ R_386_32))
{
struct elf_dyn_relocs *p;
struct elf_dyn_relocs **head;
@@ -2704,7 +2710,7 @@ elf_i386_relocate_section (bfd *output_bfd,
|| is_vxworks_tls)
break;
- if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type,
+ if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, sec,
FALSE, resolved_to_zero,
(r_type == R_386_PC32)))
{
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 90e2702334..9917447449 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1879,6 +1879,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
const char *name;
bfd_boolean size_reloc;
bfd_boolean converted_reloc;
+ bfd_boolean no_dynreloc;
r_symndx = htab->r_sym (rel->r_info);
r_type = ELF32_R_TYPE (rel->r_info);
@@ -1928,6 +1929,10 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
h = (struct elf_link_hash_entry *) h->root.u.i.link;
}
+ if (!_bfd_elf_x86_valid_reloc_p (sec, info, rel, h, isym,
+ symtab_hdr, &no_dynreloc))
+ return FALSE;
+
/* Check invalid x32 relocations. */
if (!ABI_64_P (abfd))
switch (r_type)
@@ -2245,8 +2250,9 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
size_reloc = FALSE;
do_size:
- if (NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type,
- htab->pointer_r_type))
+ if (!no_dynreloc
+ && NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type,
+ htab->pointer_r_type))
{
struct elf_dyn_relocs *p;
struct elf_dyn_relocs **head;
@@ -3175,7 +3181,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
&& (X86_PCREL_TYPE_P (r_type)
|| X86_SIZE_TYPE_P (r_type)));
- if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type,
+ if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, sec,
need_copy_reloc_in_pie,
resolved_to_zero, FALSE))
{
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 108e04a158..1c05cb28aa 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -952,6 +952,83 @@ _bfd_x86_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
return _bfd_elf_link_check_relocs (abfd, info);
}
+bfd_boolean
+_bfd_elf_x86_valid_reloc_p (asection *input_section,
+ struct bfd_link_info *info,
+ const Elf_Internal_Rela *rel,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym,
+ Elf_Internal_Shdr *symtab_hdr,
+ bfd_boolean *no_dynreloc_p)
+{
+ bfd_boolean valid_p = TRUE;
+
+ *no_dynreloc_p = FALSE;
+
+ /* Check If relocation against non-preemptible absolute symbol is
+ valid in PIC. FIXME: Can't use SYMBOL_REFERENCES_LOCAL_P since
+ it may call _bfd_elf_link_hide_sym_by_version and result in
+ ld-elfvers/ vers21 test failure. */
+ if (bfd_link_pic (info)
+ && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, h)))
+ {
+ const struct elf_backend_data *bed;
+ unsigned int r_type;
+
+ /* Skip non-absolute symbol. */
+ if (h)
+ {
+ if (!bfd_is_abs_symbol (&h->root))
+ return valid_p;
+ }
+ else if (sym->st_shndx != SHN_ABS)
+ return valid_p;
+
+ bed = get_elf_backend_data (input_section->owner);
+ r_type = ELF32_R_TYPE (rel->r_info);
+
+ /* Only allow S - A relocations against absolute symbol. */
+ if (bed->target_id == X86_64_ELF_DATA)
+ valid_p = (r_type == R_X86_64_64
+ || r_type == R_X86_64_32
+ || r_type == R_X86_64_16
+ || r_type == R_X86_64_8);
+ else
+ valid_p = (r_type == R_386_32
+ || r_type == R_386_16
+ || r_type == R_386_8);
+
+ if (valid_p)
+ *no_dynreloc_p = TRUE;
+ else
+ {
+ const char *name;
+ arelent internal_reloc;
+
+ if (!bed->elf_info_to_howto (input_section->owner,
+ &internal_reloc,
+ (Elf_Internal_Rela *) rel)
+ || internal_reloc.howto == NULL)
+ abort ();
+
+ if (h)
+ name = h->root.root.string;
+ else
+ name = bfd_elf_sym_name (input_section->owner, symtab_hdr,
+ sym, NULL);
+ info->callbacks->einfo
+ /* xgettext:c-format */
+ (_("%X%P: %pB: relocation %s against absolute symbol "
+ "`%s' in section `%pA' is disallowed\n"),
+ input_section->owner, internal_reloc.howto->name, name,
+ input_section);
+ bfd_set_error (bfd_error_bad_value);
+ }
+ }
+
+ return valid_p;
+}
+
/* Set the sizes of the dynamic sections. */
bfd_boolean
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index bef17dc2ba..5d44d413ee 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -119,11 +119,15 @@
Copy dynamic function pointer relocations. Don't generate dynamic
relocations against resolved undefined weak symbols in PIE, except
when PC32_RELOC is TRUE. Undefined weak symbol is bound locally
- when PIC is false. */
-#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, \
+ when PIC is false. Don't generate dynamic relocations against
+ non-preemptible absolute symbol. */
+#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, SEC, \
NEED_COPY_RELOC_IN_PIE, \
RESOLVED_TO_ZERO, PC32_RELOC) \
((bfd_link_pic (INFO) \
+ && !(bfd_is_abs_section (SEC) \
+ && ((EH) == NULL \
+ || SYMBOL_REFERENCES_LOCAL (INFO, &(EH)->elf))) \
&& !(NEED_COPY_RELOC_IN_PIE) \
&& ((EH) == NULL \
|| ((ELF_ST_VISIBILITY ((EH)->elf.other) == STV_DEFAULT \
@@ -652,6 +656,11 @@ extern int _bfd_x86_elf_compare_relocs
extern bfd_boolean _bfd_x86_elf_link_check_relocs
(bfd *, struct bfd_link_info *);
+extern bfd_boolean _bfd_elf_x86_valid_reloc_p
+ (asection *, struct bfd_link_info *, const Elf_Internal_Rela *,
+ struct elf_link_hash_entry *, Elf_Internal_Sym *, Elf_Internal_Shdr *,
+ bfd_boolean *);
+
extern bfd_boolean _bfd_x86_elf_size_dynamic_sections
(bfd *, struct bfd_link_info *);
diff --git a/ld/testsuite/ld-elf/linux-x86.exp b/ld/testsuite/ld-elf/linux-x86.exp
index 63a321b966..3162ac6ca5 100644
--- a/ld/testsuite/ld-elf/linux-x86.exp
+++ b/ld/testsuite/ld-elf/linux-x86.exp
@@ -115,3 +115,136 @@ 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" \
+ ] \
+ ]
+ 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" ""
+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-1d" "pr25749-1.c" "pr25749-1b.c" "-fPIC" "-shared -Wl,-Bsymbolic" "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" ""
+
+proc check_pr25749b {testname srcfilea srcfileb cflags ldflags} {
+ 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" \
+ "-shared 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-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-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 0000000000..5b37af08c6
--- /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 0000000000..775623b8c9
--- /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 0000000000..f02a408700
--- /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 0000000000..bb389172f1
--- /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 0000000000..f2847d7f62
--- /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-2.c b/ld/testsuite/ld-elf/pr25749-2.c
new file mode 100644
index 0000000000..820bebc167
--- /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 0000000000..df486fe329
--- /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 0000000000..ba82c450bc
--- /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 0000000000..fbc68bf268
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749.rd
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f ]+R_.*_NONE.*
+#...
--
2.25.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* V3 [PATCH] x86: Only allow S - A relocations against absolute symbol
2020-03-31 14:31 ` H.J. Lu
@ 2020-03-31 23:25 ` H.J. Lu
2020-04-01 3:30 ` V4 " H.J. Lu
0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2020-03-31 23:25 UTC (permalink / raw)
To: Fangrui Song; +Cc: H.J. Lu via Binutils
[-- Attachment #1: Type: text/plain, Size: 1521 bytes --]
On Tue, Mar 31, 2020 at 7:31 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Mon, Mar 30, 2020 at 11:18 PM Fangrui Song <i@maskray.me> wrote:
> >
> > On 2020-03-30, H.J. Lu via Binutils wrote:
> > >Since value of non-preemptible absolute symbol (SHN_ABS) won't change,
> > >only S - A relocations against non-preemptible absolute symbol are
> > >allowed in PIE and shared library.
> >
> > Thanks for the patch. At some point we should define some generic
> > relocation categories (https://reviews.llvm.org/rL266158). For example,
> >
> > - R_ABS: R_X86_64_8, R_X86_64_16, R_X86_64_32, R_X86_64_64
> > R_AARCH64_ABS16, R_AARCH64_ABS32, R_AARCH64_ABS64
> > R_PPC64_ADDR16, R_PPC64_ADDR16_DS, R_PPC64_ADDR16_HA, ...
> > - R_PCREL: R_X86_64_PC8, R_X86_64_PC16, R_X86_64_PC32, R_X86_64_PC64
> > R_AARCH64_PREL16, R_AARCH64_PREL32, R_AARCH64_PREL64
> > - R_PLT_PCREL: R_X86_64_PLT32, R_AARCH64_CALL26
> > - R_GOT_PCREL: R_X86_64_GOTPCREL, R_X86_64_GOTPCRELX
> >
> > Define a property is_preemptible as a more appropriate level of
> > abstraction for GENERATE_DYNAMIC_RELOCATION_P and some use cases of bfd_link_pic and bfd_link_executable...
>
> Current BFD linker delegates most, if not all, of relocation to each backend.
> There are many similar codes in backends. I am sharing as much codes
> between i386 and x86-64 backends as I can.
>
> This is the patch I am checking in.
Here is the updated patch to include the fix for
https://sourceware.org/bugzilla/show_bug.cgi?id=25754
--
H.J.
[-- Attachment #2: 0001-x86-Only-allow-S-A-relocations-against-absolute-symb.patch --]
[-- Type: application/x-patch, Size: 24478 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* V4 [PATCH] x86: Only allow S - A relocations against absolute symbol
2020-03-31 23:25 ` V3 " H.J. Lu
@ 2020-04-01 3:30 ` H.J. Lu
2020-04-01 14:06 ` V5 " H.J. Lu
0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2020-04-01 3:30 UTC (permalink / raw)
To: Fangrui Song; +Cc: H.J. Lu via Binutils
[-- Attachment #1: Type: text/plain, Size: 1702 bytes --]
On Tue, Mar 31, 2020 at 4:25 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, Mar 31, 2020 at 7:31 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Mon, Mar 30, 2020 at 11:18 PM Fangrui Song <i@maskray.me> wrote:
> > >
> > > On 2020-03-30, H.J. Lu via Binutils wrote:
> > > >Since value of non-preemptible absolute symbol (SHN_ABS) won't change,
> > > >only S - A relocations against non-preemptible absolute symbol are
> > > >allowed in PIE and shared library.
> > >
> > > Thanks for the patch. At some point we should define some generic
> > > relocation categories (https://reviews.llvm.org/rL266158). For example,
> > >
> > > - R_ABS: R_X86_64_8, R_X86_64_16, R_X86_64_32, R_X86_64_64
> > > R_AARCH64_ABS16, R_AARCH64_ABS32, R_AARCH64_ABS64
> > > R_PPC64_ADDR16, R_PPC64_ADDR16_DS, R_PPC64_ADDR16_HA, ...
> > > - R_PCREL: R_X86_64_PC8, R_X86_64_PC16, R_X86_64_PC32, R_X86_64_PC64
> > > R_AARCH64_PREL16, R_AARCH64_PREL32, R_AARCH64_PREL64
> > > - R_PLT_PCREL: R_X86_64_PLT32, R_AARCH64_CALL26
> > > - R_GOT_PCREL: R_X86_64_GOTPCREL, R_X86_64_GOTPCRELX
> > >
> > > Define a property is_preemptible as a more appropriate level of
> > > abstraction for GENERATE_DYNAMIC_RELOCATION_P and some use cases of bfd_link_pic and bfd_link_executable...
> >
> > Current BFD linker delegates most, if not all, of relocation to each backend.
> > There are many similar codes in backends. I am sharing as much codes
> > between i386 and x86-64 backends as I can.
> >
> > This is the patch I am checking in.
>
> Here is the updated patch to include the fix for
>
> https://sourceware.org/bugzilla/show_bug.cgi?id=25754
>
Another update to allow GOTPCREL relocations.
--
H.J.
[-- Attachment #2: 0001-x86-Only-allow-S-A-relocations-against-absolute-symb.patch --]
[-- Type: text/x-patch, Size: 29838 bytes --]
From ca5b16ca18f16751a51f6732c6170488d012fb09 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 30 Mar 2020 18:36:39 -0700
Subject: [PATCH] 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.
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.
(elf_x86_64_check_relocs): Call
_bfd_elf_x86_valid_reloc_p. Don't allocate dynamic relocation
for non-preemptible absolute symbol.
(elf_x86_64_relocate_section): 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.
* elfxx-x86.h (GENERATE_DYNAMIC_RELOCATION_P): Add an SEC
argument. Don't generate dynamic relocation against
non-preemptible absolute symbol.
(GENERATE_RELATIVE_RELOC_P): Don't generate relative relocation
against non-preemptible absolute symbol.
(R_X86_64_converted_reloc_bit): New. Moved from elf64-x86-64.c.
(_bfd_elf_x86_valid_reloc_p): Likewise.
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-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.
---
bfd/elf32-i386.c | 40 +++++---
bfd/elf64-x86-64.c | 31 ++++--
bfd/elfxx-x86.c | 101 ++++++++++++++++++-
bfd/elfxx-x86.h | 22 ++++-
ld/testsuite/ld-elf/linux-x86.exp | 150 +++++++++++++++++++++++++++++
ld/testsuite/ld-elf/pr25749-1.c | 12 +++
ld/testsuite/ld-elf/pr25749-1a.c | 11 +++
ld/testsuite/ld-elf/pr25749-1b.c | 9 ++
ld/testsuite/ld-elf/pr25749-1b.err | 3 +
ld/testsuite/ld-elf/pr25749-1c.c | 9 ++
ld/testsuite/ld-elf/pr25749-2.c | 12 +++
ld/testsuite/ld-elf/pr25749-2a.s | 6 ++
ld/testsuite/ld-elf/pr25749-2b.s | 7 ++
ld/testsuite/ld-elf/pr25749.rd | 4 +
ld/testsuite/ld-elf/pr25754-1a.c | 19 ++++
ld/testsuite/ld-elf/pr25754-1b.s | 3 +
ld/testsuite/ld-elf/pr25754-2a.c | 19 ++++
ld/testsuite/ld-elf/pr25754-2b.err | 3 +
ld/testsuite/ld-elf/pr25754-2b.s | 3 +
ld/testsuite/ld-elf/pr25754-3a.c | 19 ++++
ld/testsuite/ld-elf/pr25754-3b.s | 3 +
21 files changed, 461 insertions(+), 25 deletions(-)
create mode 100644 ld/testsuite/ld-elf/pr25749-1.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1a.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1b.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1b.err
create mode 100644 ld/testsuite/ld-elf/pr25749-1c.c
create mode 100644 ld/testsuite/ld-elf/pr25749-2.c
create mode 100644 ld/testsuite/ld-elf/pr25749-2a.s
create mode 100644 ld/testsuite/ld-elf/pr25749-2b.s
create mode 100644 ld/testsuite/ld-elf/pr25749.rd
create mode 100644 ld/testsuite/ld-elf/pr25754-1a.c
create mode 100644 ld/testsuite/ld-elf/pr25754-1b.s
create mode 100644 ld/testsuite/ld-elf/pr25754-2a.c
create mode 100644 ld/testsuite/ld-elf/pr25754-2b.err
create mode 100644 ld/testsuite/ld-elf/pr25754-2b.s
create mode 100644 ld/testsuite/ld-elf/pr25754-3a.c
create mode 100644 ld/testsuite/ld-elf/pr25754-3b.s
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index eb7e1f8b34..20dfa4b4f4 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1226,6 +1226,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
bfd_vma nop_offset;
bfd_boolean is_pic;
bfd_boolean to_reloc_32;
+ bfd_boolean abs_symbol;
unsigned int r_type;
unsigned int r_symndx;
bfd_vma roff = irel->r_offset;
@@ -1249,6 +1250,21 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
modrm = bfd_get_8 (abfd, contents + roff - 1);
baseless = (modrm & 0xc7) == 0x5;
+ if (h)
+ {
+ /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */
+ local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h);
+ isym = NULL;
+ abs_symbol = bfd_is_abs_symbol (&h->root);
+ }
+ else
+ {
+ local_ref = TRUE;
+ isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd,
+ r_symndx);
+ abs_symbol = isym->st_shndx == SHN_ABS;
+ }
+
if (baseless && is_pic)
{
/* For PIC, disallow R_386_GOT32X without a base register
@@ -1256,11 +1272,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
const char *name;
if (h == NULL)
- {
- isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd,
- r_symndx);
- name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
- }
+ name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
else
name = h->root.root.string;
@@ -1294,9 +1306,6 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
goto convert_load;
}
- /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */
- local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h);
-
/* Undefined weak symbol is only bound locally in executable
and its reference is resolved as 0. */
if (h->root.type == bfd_link_hash_undefweak
@@ -1396,6 +1405,9 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
convert_load:
if (opcode == 0x8b)
{
+ if (abs_symbol && local_ref)
+ to_reloc_32 = TRUE;
+
if (to_reloc_32)
{
/* Convert "mov foo@GOT[(%reg1)], %reg2" to
@@ -1519,6 +1531,7 @@ elf_i386_check_relocs (bfd *abfd,
Elf_Internal_Sym *isym;
const char *name;
bfd_boolean size_reloc;
+ bfd_boolean no_dynreloc;
r_symndx = ELF32_R_SYM (rel->r_info);
r_type = ELF32_R_TYPE (rel->r_info);
@@ -1587,6 +1600,10 @@ elf_i386_check_relocs (bfd *abfd,
goto error_return;
}
+ if (!_bfd_elf_x86_valid_reloc_p (sec, info, htab, rel, h, isym,
+ symtab_hdr, &no_dynreloc))
+ return FALSE;
+
if (! elf_i386_tls_transition (info, abfd, sec, contents,
symtab_hdr, sym_hashes,
&r_type, GOT_UNKNOWN,
@@ -1827,8 +1844,9 @@ elf_i386_check_relocs (bfd *abfd,
size_reloc = FALSE;
do_size:
- if (NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type,
- R_386_32))
+ if (!no_dynreloc
+ && NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type,
+ R_386_32))
{
struct elf_dyn_relocs *p;
struct elf_dyn_relocs **head;
@@ -2704,7 +2722,7 @@ elf_i386_relocate_section (bfd *output_bfd,
|| is_vxworks_tls)
break;
- if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type,
+ if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, sec,
FALSE, resolved_to_zero,
(r_type == R_386_PC32)))
{
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 90e2702334..68f00c1973 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -196,9 +196,6 @@ static reloc_howto_type x86_64_elf_howto_table[] =
FALSE)
};
-/* Set if a relocation is converted from a GOTPCREL relocation. */
-#define R_X86_64_converted_reloc_bit (1 << 7)
-
#define X86_PCREL_TYPE_P(TYPE) \
( ((TYPE) == R_X86_64_PC8) \
|| ((TYPE) == R_X86_64_PC16) \
@@ -1509,6 +1506,8 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
bfd_boolean no_overflow;
bfd_boolean relocx;
bfd_boolean to_reloc_pc32;
+ bfd_boolean abs_symbol;
+ bfd_boolean local_ref;
asection *tsec;
bfd_signed_vma raddend;
unsigned int opcode;
@@ -1559,6 +1558,8 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
|| no_overflow
|| is_pic);
+ abs_symbol = FALSE;
+
/* Get the symbol referred to by the reloc. */
if (h == NULL)
{
@@ -1569,8 +1570,12 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
if (isym->st_shndx == SHN_UNDEF)
return TRUE;
+ local_ref = TRUE;
if (isym->st_shndx == SHN_ABS)
- tsec = bfd_abs_section_ptr;
+ {
+ tsec = bfd_abs_section_ptr;
+ abs_symbol = TRUE;
+ }
else if (isym->st_shndx == SHN_COMMON)
tsec = bfd_com_section_ptr;
else if (isym->st_shndx == SHN_X86_64_LCOMMON)
@@ -1586,9 +1591,10 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
GOTPCRELX relocations since we need to modify REX byte.
It is OK convert mov with R_X86_64_GOTPCREL to
R_X86_64_PC32. */
- bfd_boolean local_ref;
struct elf_x86_link_hash_entry *eh = elf_x86_hash_entry (h);
+ abs_symbol = bfd_is_abs_symbol (&h->root);
+
/* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */
local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h);
if ((relocx || opcode == 0x8b)
@@ -1728,6 +1734,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
if (opcode == 0x8b)
{
+ if (abs_symbol && local_ref)
+ to_reloc_pc32 = FALSE;
+
if (to_reloc_pc32)
{
/* Convert "mov foo@GOTPCREL(%rip), %reg" to
@@ -1879,6 +1888,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
const char *name;
bfd_boolean size_reloc;
bfd_boolean converted_reloc;
+ bfd_boolean no_dynreloc;
r_symndx = htab->r_sym (rel->r_info);
r_type = ELF32_R_TYPE (rel->r_info);
@@ -1983,6 +1993,10 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
converted = TRUE;
}
+ if (!_bfd_elf_x86_valid_reloc_p (sec, info, htab, rel, h, isym,
+ symtab_hdr, &no_dynreloc))
+ return FALSE;
+
if (! elf_x86_64_tls_transition (info, abfd, sec, contents,
symtab_hdr, sym_hashes,
&r_type, GOT_UNKNOWN,
@@ -2245,8 +2259,9 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
size_reloc = FALSE;
do_size:
- if (NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type,
- htab->pointer_r_type))
+ if (!no_dynreloc
+ && NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type,
+ htab->pointer_r_type))
{
struct elf_dyn_relocs *p;
struct elf_dyn_relocs **head;
@@ -3175,7 +3190,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
&& (X86_PCREL_TYPE_P (r_type)
|| X86_SIZE_TYPE_P (r_type)));
- if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type,
+ if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, sec,
need_copy_reloc_in_pie,
resolved_to_zero, FALSE))
{
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 108e04a158..8ebbbe2fd5 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -347,7 +347,8 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
(but if both R_386_TLS_IE_32 and R_386_TLS_IE is present, we
need two), R_386_TLS_GD and R_X86_64_TLSGD need one if local
symbol and two if global. No dynamic relocation against
- resolved undefined weak symbol in executable. */
+ resolved undefined weak symbol in executable. No dynamic
+ relocation against non-preemptible absolute symbol. */
if (tls_type == GOT_TLS_IE_BOTH)
htab->elf.srelgot->size += 2 * htab->sizeof_reloc;
else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1)
@@ -359,7 +360,9 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
&& ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
&& !resolved_to_zero)
|| h->root.type != bfd_link_hash_undefweak)
- && (bfd_link_pic (info)
+ && ((bfd_link_pic (info)
+ && !(h->dynindx == -1
+ && bfd_is_abs_symbol (&h->root)))
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
htab->elf.srelgot->size += htab->sizeof_reloc;
if (GOT_TLS_GDESC_P (tls_type))
@@ -952,6 +955,100 @@ _bfd_x86_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
return _bfd_elf_link_check_relocs (abfd, info);
}
+bfd_boolean
+_bfd_elf_x86_valid_reloc_p (asection *input_section,
+ struct bfd_link_info *info,
+ struct elf_x86_link_hash_table *htab,
+ const Elf_Internal_Rela *rel,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym,
+ Elf_Internal_Shdr *symtab_hdr,
+ bfd_boolean *no_dynreloc_p)
+{
+ bfd_boolean valid_p = TRUE;
+
+ *no_dynreloc_p = FALSE;
+
+ /* Check If relocation against non-preemptible absolute symbol is
+ valid in PIC. FIXME: Can't use SYMBOL_REFERENCES_LOCAL_P since
+ it may call _bfd_elf_link_hide_sym_by_version and result in
+ ld-elfvers/ vers21 test failure. */
+ if (bfd_link_pic (info)
+ && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, h)))
+ {
+ const struct elf_backend_data *bed;
+ unsigned int r_type;
+ Elf_Internal_Rela irel;
+
+ /* Skip non-absolute symbol. */
+ if (h)
+ {
+ if (!bfd_is_abs_symbol (&h->root))
+ return valid_p;
+ }
+ else if (sym->st_shndx != SHN_ABS)
+ return valid_p;
+
+ bed = get_elf_backend_data (input_section->owner);
+ r_type = ELF32_R_TYPE (rel->r_info);
+ irel = *rel;
+
+ /* Only allow relocations against absolute symbol, which can be
+ resolved as absolute value + addend. GOTPCREL relocations
+ are allowed since absolute value + addend is stored in the
+ GOT slot. */
+ if (bed->target_id == X86_64_ELF_DATA)
+ {
+ r_type &= ~R_X86_64_converted_reloc_bit;
+ valid_p = (r_type == R_X86_64_64
+ || r_type == R_X86_64_32
+ || r_type == R_X86_64_32S
+ || r_type == R_X86_64_16
+ || r_type == R_X86_64_8
+ || r_type == R_X86_64_GOTPCREL
+ || r_type == R_X86_64_GOTPCRELX
+ || r_type == R_X86_64_REX_GOTPCRELX);
+ if (!valid_p)
+ {
+ unsigned int r_symndx = htab->r_sym (rel->r_info);
+ irel.r_info = htab->r_info (r_symndx, r_type);
+ }
+ }
+ else
+ valid_p = (r_type == R_386_32
+ || r_type == R_386_16
+ || r_type == R_386_8);
+
+ if (valid_p)
+ *no_dynreloc_p = TRUE;
+ else
+ {
+ const char *name;
+ arelent internal_reloc;
+
+ if (!bed->elf_info_to_howto (input_section->owner,
+ &internal_reloc, &irel)
+ || internal_reloc.howto == NULL)
+ abort ();
+
+ if (h)
+ name = h->root.root.string;
+ else
+ name = bfd_elf_sym_name (input_section->owner, symtab_hdr,
+ sym, NULL);
+ info->callbacks->einfo
+ /* xgettext:c-format */
+ (_("%F%P: %pB: relocation %s against absolute symbol "
+ "`%s' in section `%pA' is disallowed\n"),
+ input_section->owner, internal_reloc.howto->name, name,
+ input_section);
+ bfd_set_error (bfd_error_bad_value);
+ }
+ }
+
+ return valid_p;
+}
+
/* Set the sizes of the dynamic sections. */
bfd_boolean
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index bef17dc2ba..4757f770e6 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -119,11 +119,15 @@
Copy dynamic function pointer relocations. Don't generate dynamic
relocations against resolved undefined weak symbols in PIE, except
when PC32_RELOC is TRUE. Undefined weak symbol is bound locally
- when PIC is false. */
-#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, \
+ when PIC is false. Don't generate dynamic relocations against
+ non-preemptible absolute symbol. */
+#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, SEC, \
NEED_COPY_RELOC_IN_PIE, \
RESOLVED_TO_ZERO, PC32_RELOC) \
((bfd_link_pic (INFO) \
+ && !(bfd_is_abs_section (SEC) \
+ && ((EH) == NULL \
+ || SYMBOL_REFERENCES_LOCAL (INFO, &(EH)->elf))) \
&& !(NEED_COPY_RELOC_IN_PIE) \
&& ((EH) == NULL \
|| ((ELF_ST_VISIBILITY ((EH)->elf.other) == STV_DEFAULT \
@@ -175,12 +179,14 @@
problem when "time" or "times" is defined as a variable in an
executable, clashing with functions of the same name in libc. If a
symbol isn't undefined weak symbol, don't make it dynamic in PIC and
- generate relative relocation. */
+ generate relative relocation. Don't generate relative relocation
+ against non-preemptible absolute symbol. */
#define GENERATE_RELATIVE_RELOC_P(INFO, H) \
((H)->dynindx == -1 \
&& !(H)->forced_local \
&& (H)->root.type != bfd_link_hash_undefweak \
- && bfd_link_pic (INFO))
+ && bfd_link_pic (INFO) \
+ && !bfd_is_abs_symbol (&(H)->root))
/* TRUE if this is a pointer reference to a local IFUNC. */
#define POINTER_LOCAL_IFUNC_P(INFO, H) \
@@ -601,6 +607,9 @@ struct elf_x86_plt
long count;
};
+/* Set if a relocation is converted from a GOTPCREL relocation. */
+#define R_X86_64_converted_reloc_bit (1 << 7)
+
#define elf_x86_tdata(abfd) \
((struct elf_x86_obj_tdata *) (abfd)->tdata.any)
@@ -652,6 +661,11 @@ extern int _bfd_x86_elf_compare_relocs
extern bfd_boolean _bfd_x86_elf_link_check_relocs
(bfd *, struct bfd_link_info *);
+extern bfd_boolean _bfd_elf_x86_valid_reloc_p
+ (asection *, struct bfd_link_info *, struct elf_x86_link_hash_table *,
+ const Elf_Internal_Rela *, struct elf_link_hash_entry *,
+ Elf_Internal_Sym *, Elf_Internal_Shdr *, bfd_boolean *);
+
extern bfd_boolean _bfd_x86_elf_size_dynamic_sections
(bfd *, struct bfd_link_info *);
diff --git a/ld/testsuite/ld-elf/linux-x86.exp b/ld/testsuite/ld-elf/linux-x86.exp
index 63a321b966..7ec6a0c8e9 100644
--- a/ld/testsuite/ld-elf/linux-x86.exp
+++ b/ld/testsuite/ld-elf/linux-x86.exp
@@ -115,3 +115,153 @@ 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" \
+ ] \
+ ]
+ 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 -Wl,--no-relax" ""
+ check_pr25749a "pr25754-2b" "pr25754-2a.c" "pr25754-2b.s" "-fPIC" "-pie -Wl,--no-relax" ""
+ check_pr25749a "pr25754-2c" "pr25754-2a.c" "pr25754-2b.s" "-fPIC" "-pie" "pr25754-2b.err"
+} 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" ""
+}
+
+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-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 0000000000..5b37af08c6
--- /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 0000000000..775623b8c9
--- /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 0000000000..f02a408700
--- /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 0000000000..bb389172f1
--- /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 0000000000..f2847d7f62
--- /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-2.c b/ld/testsuite/ld-elf/pr25749-2.c
new file mode 100644
index 0000000000..820bebc167
--- /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 0000000000..df486fe329
--- /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 0000000000..ba82c450bc
--- /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 0000000000..fbc68bf268
--- /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 0000000000..266a1e360b
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-1a.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <bfd_stdint.h>
+
+extern intptr_t bar;
+
+intptr_t *
+__attribute__ ((noinline, noclone))
+get_bar (void)
+{
+ return &bar;
+}
+
+int
+main ()
+{
+ if ((intptr_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 0000000000..99d585d6b5
--- /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 0000000000..099797672a
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-2a.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <bfd_stdint.h>
+
+extern intptr_t bar;
+
+intptr_t *
+__attribute__ ((noinline, noclone))
+get_bar (void)
+{
+ return &bar;
+}
+
+int
+main ()
+{
+ if ((intptr_t) get_bar () == -0x80000001L)
+ printf ("PASS\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/pr25754-2b.err b/ld/testsuite/ld-elf/pr25754-2b.err
new file mode 100644
index 0000000000..c173122ee3
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-2b.err
@@ -0,0 +1,3 @@
+#...
+.*: failed to convert GOTPCREL relocation; relink with --no-relax
+#pass
diff --git a/ld/testsuite/ld-elf/pr25754-2b.s b/ld/testsuite/ld-elf/pr25754-2b.s
new file mode 100644
index 0000000000..aad3e45e0f
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-2b.s
@@ -0,0 +1,3 @@
+ .data
+ .global bar
+ bar = -0x80000001
diff --git a/ld/testsuite/ld-elf/pr25754-3a.c b/ld/testsuite/ld-elf/pr25754-3a.c
new file mode 100644
index 0000000000..72c620c8a8
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-3a.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <bfd_stdint.h>
+
+extern intptr_t bar;
+
+intptr_t *
+__attribute__ ((noinline, noclone))
+get_bar (void)
+{
+ return &bar;
+}
+
+int
+main ()
+{
+ if ((intptr_t) get_bar () == 0xfffffff0U)
+ 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 0000000000..9cab99303e
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25754-3b.s
@@ -0,0 +1,3 @@
+ .data
+ .global bar
+ bar = 0xfffffff0
--
2.25.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* V5 [PATCH] x86: Only allow S - A relocations against absolute symbol
2020-04-01 3:30 ` V4 " H.J. Lu
@ 2020-04-01 14:06 ` H.J. Lu
2020-04-01 21:28 ` V6 " H.J. Lu
0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2020-04-01 14:06 UTC (permalink / raw)
To: Fangrui Song; +Cc: H.J. Lu via Binutils
[-- Attachment #1: Type: text/plain, Size: 1899 bytes --]
On Tue, Mar 31, 2020 at 8:30 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, Mar 31, 2020 at 4:25 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Tue, Mar 31, 2020 at 7:31 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > On Mon, Mar 30, 2020 at 11:18 PM Fangrui Song <i@maskray.me> wrote:
> > > >
> > > > On 2020-03-30, H.J. Lu via Binutils wrote:
> > > > >Since value of non-preemptible absolute symbol (SHN_ABS) won't change,
> > > > >only S - A relocations against non-preemptible absolute symbol are
> > > > >allowed in PIE and shared library.
> > > >
> > > > Thanks for the patch. At some point we should define some generic
> > > > relocation categories (https://reviews.llvm.org/rL266158). For example,
> > > >
> > > > - R_ABS: R_X86_64_8, R_X86_64_16, R_X86_64_32, R_X86_64_64
> > > > R_AARCH64_ABS16, R_AARCH64_ABS32, R_AARCH64_ABS64
> > > > R_PPC64_ADDR16, R_PPC64_ADDR16_DS, R_PPC64_ADDR16_HA, ...
> > > > - R_PCREL: R_X86_64_PC8, R_X86_64_PC16, R_X86_64_PC32, R_X86_64_PC64
> > > > R_AARCH64_PREL16, R_AARCH64_PREL32, R_AARCH64_PREL64
> > > > - R_PLT_PCREL: R_X86_64_PLT32, R_AARCH64_CALL26
> > > > - R_GOT_PCREL: R_X86_64_GOTPCREL, R_X86_64_GOTPCRELX
> > > >
> > > > Define a property is_preemptible as a more appropriate level of
> > > > abstraction for GENERATE_DYNAMIC_RELOCATION_P and some use cases of bfd_link_pic and bfd_link_executable...
> > >
> > > Current BFD linker delegates most, if not all, of relocation to each backend.
> > > There are many similar codes in backends. I am sharing as much codes
> > > between i386 and x86-64 backends as I can.
> > >
> > > This is the patch I am checking in.
> >
> > Here is the updated patch to include the fix for
> >
> > https://sourceware.org/bugzilla/show_bug.cgi?id=25754
> >
>
> Another update to allow GOTPCREL relocations.
Update to detect R_X86_64_32S/R_X86_64_32 overflow.
--
H.J.
[-- Attachment #2: 0001-x86-Only-allow-S-A-relocations-against-absolute-symb.patch --]
[-- Type: text/x-patch, Size: 39575 bytes --]
From 3b7ce8890732d8521c7561e0fb5066eac4f4bdb5 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 30 Mar 2020 18:36:39 -0700
Subject: [PATCH] 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.
(GENERATE_RELATIVE_RELOC_P): Don't generate relative relocation
against non-preemptible absolute symbol.
(R_X86_64_converted_reloc_bit): New. Moved from elf64-x86-64.c.
(_bfd_elf_x86_valid_reloc_p): Likewise.
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-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.
---
bfd/elf32-i386.c | 40 +++++--
bfd/elf64-x86-64.c | 81 +++++++++++---
bfd/elfxx-x86.c | 103 ++++++++++++++++-
bfd/elfxx-x86.h | 23 +++-
ld/testsuite/ld-elf/linux-x86.exp | 164 ++++++++++++++++++++++++++++
ld/testsuite/ld-elf/pr25749-1.c | 12 ++
ld/testsuite/ld-elf/pr25749-1a.c | 11 ++
ld/testsuite/ld-elf/pr25749-1b.c | 9 ++
ld/testsuite/ld-elf/pr25749-1b.err | 3 +
ld/testsuite/ld-elf/pr25749-1c.c | 9 ++
ld/testsuite/ld-elf/pr25749-2.c | 12 ++
ld/testsuite/ld-elf/pr25749-2a.s | 6 +
ld/testsuite/ld-elf/pr25749-2b.s | 7 ++
ld/testsuite/ld-elf/pr25749.rd | 4 +
ld/testsuite/ld-elf/pr25754-1a.c | 19 ++++
ld/testsuite/ld-elf/pr25754-1b.s | 3 +
ld/testsuite/ld-elf/pr25754-2a.c | 20 ++++
ld/testsuite/ld-elf/pr25754-2b.s | 3 +
ld/testsuite/ld-elf/pr25754-3a.c | 19 ++++
ld/testsuite/ld-elf/pr25754-3b.s | 3 +
ld/testsuite/ld-elf/pr25754-4a.c | 12 ++
ld/testsuite/ld-elf/pr25754-4b.s | 23 ++++
ld/testsuite/ld-elf/pr25754-4c.s | 12 ++
ld/testsuite/ld-elf/pr25754-5a.c | 12 ++
ld/testsuite/ld-elf/pr25754-5b.s | 23 ++++
ld/testsuite/ld-elf/pr25754-5c.s | 12 ++
ld/testsuite/ld-elf/pr25754-6a.c | 12 ++
ld/testsuite/ld-elf/pr25754-6b.s | 12 ++
ld/testsuite/ld-x86-64/pr19609-6a.d | 11 +-
29 files changed, 648 insertions(+), 32 deletions(-)
create mode 100644 ld/testsuite/ld-elf/pr25749-1.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1a.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1b.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1b.err
create mode 100644 ld/testsuite/ld-elf/pr25749-1c.c
create mode 100644 ld/testsuite/ld-elf/pr25749-2.c
create mode 100644 ld/testsuite/ld-elf/pr25749-2a.s
create mode 100644 ld/testsuite/ld-elf/pr25749-2b.s
create mode 100644 ld/testsuite/ld-elf/pr25749.rd
create mode 100644 ld/testsuite/ld-elf/pr25754-1a.c
create mode 100644 ld/testsuite/ld-elf/pr25754-1b.s
create mode 100644 ld/testsuite/ld-elf/pr25754-2a.c
create mode 100644 ld/testsuite/ld-elf/pr25754-2b.s
create mode 100644 ld/testsuite/ld-elf/pr25754-3a.c
create mode 100644 ld/testsuite/ld-elf/pr25754-3b.s
create mode 100644 ld/testsuite/ld-elf/pr25754-4a.c
create mode 100644 ld/testsuite/ld-elf/pr25754-4b.s
create mode 100644 ld/testsuite/ld-elf/pr25754-4c.s
create mode 100644 ld/testsuite/ld-elf/pr25754-5a.c
create mode 100644 ld/testsuite/ld-elf/pr25754-5b.s
create mode 100644 ld/testsuite/ld-elf/pr25754-5c.s
create mode 100644 ld/testsuite/ld-elf/pr25754-6a.c
create mode 100644 ld/testsuite/ld-elf/pr25754-6b.s
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index eb7e1f8b34..20dfa4b4f4 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1226,6 +1226,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
bfd_vma nop_offset;
bfd_boolean is_pic;
bfd_boolean to_reloc_32;
+ bfd_boolean abs_symbol;
unsigned int r_type;
unsigned int r_symndx;
bfd_vma roff = irel->r_offset;
@@ -1249,6 +1250,21 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
modrm = bfd_get_8 (abfd, contents + roff - 1);
baseless = (modrm & 0xc7) == 0x5;
+ if (h)
+ {
+ /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */
+ local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h);
+ isym = NULL;
+ abs_symbol = bfd_is_abs_symbol (&h->root);
+ }
+ else
+ {
+ local_ref = TRUE;
+ isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd,
+ r_symndx);
+ abs_symbol = isym->st_shndx == SHN_ABS;
+ }
+
if (baseless && is_pic)
{
/* For PIC, disallow R_386_GOT32X without a base register
@@ -1256,11 +1272,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
const char *name;
if (h == NULL)
- {
- isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd,
- r_symndx);
- name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
- }
+ name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
else
name = h->root.root.string;
@@ -1294,9 +1306,6 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
goto convert_load;
}
- /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */
- local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h);
-
/* Undefined weak symbol is only bound locally in executable
and its reference is resolved as 0. */
if (h->root.type == bfd_link_hash_undefweak
@@ -1396,6 +1405,9 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
convert_load:
if (opcode == 0x8b)
{
+ if (abs_symbol && local_ref)
+ to_reloc_32 = TRUE;
+
if (to_reloc_32)
{
/* Convert "mov foo@GOT[(%reg1)], %reg2" to
@@ -1519,6 +1531,7 @@ elf_i386_check_relocs (bfd *abfd,
Elf_Internal_Sym *isym;
const char *name;
bfd_boolean size_reloc;
+ bfd_boolean no_dynreloc;
r_symndx = ELF32_R_SYM (rel->r_info);
r_type = ELF32_R_TYPE (rel->r_info);
@@ -1587,6 +1600,10 @@ elf_i386_check_relocs (bfd *abfd,
goto error_return;
}
+ if (!_bfd_elf_x86_valid_reloc_p (sec, info, htab, rel, h, isym,
+ symtab_hdr, &no_dynreloc))
+ return FALSE;
+
if (! elf_i386_tls_transition (info, abfd, sec, contents,
symtab_hdr, sym_hashes,
&r_type, GOT_UNKNOWN,
@@ -1827,8 +1844,9 @@ elf_i386_check_relocs (bfd *abfd,
size_reloc = FALSE;
do_size:
- if (NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type,
- R_386_32))
+ if (!no_dynreloc
+ && NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type,
+ R_386_32))
{
struct elf_dyn_relocs *p;
struct elf_dyn_relocs **head;
@@ -2704,7 +2722,7 @@ elf_i386_relocate_section (bfd *output_bfd,
|| is_vxworks_tls)
break;
- if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type,
+ if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, sec,
FALSE, resolved_to_zero,
(r_type == R_386_PC32)))
{
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 90e2702334..85d99a7f5d 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -196,9 +196,6 @@ static reloc_howto_type x86_64_elf_howto_table[] =
FALSE)
};
-/* Set if a relocation is converted from a GOTPCREL relocation. */
-#define R_X86_64_converted_reloc_bit (1 << 7)
-
#define X86_PCREL_TYPE_P(TYPE) \
( ((TYPE) == R_X86_64_PC8) \
|| ((TYPE) == R_X86_64_PC16) \
@@ -1509,6 +1506,8 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
bfd_boolean no_overflow;
bfd_boolean relocx;
bfd_boolean to_reloc_pc32;
+ bfd_boolean abs_symbol;
+ bfd_boolean local_ref;
asection *tsec;
bfd_signed_vma raddend;
unsigned int opcode;
@@ -1516,6 +1515,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
unsigned int r_type = *r_type_p;
unsigned int r_symndx;
bfd_vma roff = irel->r_offset;
+ bfd_vma abs_relocation;
if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2))
return TRUE;
@@ -1559,6 +1559,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
|| no_overflow
|| is_pic);
+ abs_symbol = FALSE;
+ abs_relocation = 0;
+
/* Get the symbol referred to by the reloc. */
if (h == NULL)
{
@@ -1569,8 +1572,13 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
if (isym->st_shndx == SHN_UNDEF)
return TRUE;
+ local_ref = TRUE;
if (isym->st_shndx == SHN_ABS)
- tsec = bfd_abs_section_ptr;
+ {
+ tsec = bfd_abs_section_ptr;
+ abs_symbol = TRUE;
+ abs_relocation = isym->st_value;
+ }
else if (isym->st_shndx == SHN_COMMON)
tsec = bfd_com_section_ptr;
else if (isym->st_shndx == SHN_X86_64_LCOMMON)
@@ -1586,9 +1594,11 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
GOTPCRELX relocations since we need to modify REX byte.
It is OK convert mov with R_X86_64_GOTPCREL to
R_X86_64_PC32. */
- bfd_boolean local_ref;
struct elf_x86_link_hash_entry *eh = elf_x86_hash_entry (h);
+ abs_symbol = bfd_is_abs_symbol (&h->root);
+ abs_relocation = h->root.u.def.value;
+
/* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */
local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h);
if ((relocx || opcode == 0x8b)
@@ -1728,6 +1738,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
if (opcode == 0x8b)
{
+ if (abs_symbol && local_ref)
+ to_reloc_pc32 = FALSE;
+
if (to_reloc_pc32)
{
/* Convert "mov foo@GOTPCREL(%rip), %reg" to
@@ -1788,6 +1801,21 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
r_type = (rex & REX_W) != 0 ? R_X86_64_32S : R_X86_64_32;
rewrite_modrm_rex:
+ if (abs_relocation)
+ {
+ /* Check if R_X86_64_32S/R_X86_64_32 fits. */
+ if (r_type == R_X86_64_32S)
+ {
+ if ((abs_relocation + 0x80000000) > 0xffffffff)
+ return TRUE;
+ }
+ else
+ {
+ if (abs_relocation > 0xffffffff)
+ return TRUE;
+ }
+ }
+
bfd_put_8 (abfd, modrm, contents + roff - 1);
if (rex)
@@ -1879,6 +1907,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
const char *name;
bfd_boolean size_reloc;
bfd_boolean converted_reloc;
+ bfd_boolean no_dynreloc;
r_symndx = htab->r_sym (rel->r_info);
r_type = ELF32_R_TYPE (rel->r_info);
@@ -1983,6 +2012,10 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
converted = TRUE;
}
+ if (!_bfd_elf_x86_valid_reloc_p (sec, info, htab, rel, h, isym,
+ symtab_hdr, &no_dynreloc))
+ return FALSE;
+
if (! elf_x86_64_tls_transition (info, abfd, sec, contents,
symtab_hdr, sym_hashes,
&r_type, GOT_UNKNOWN,
@@ -2029,12 +2062,26 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
switch (r_type)
{
- default: tls_type = GOT_NORMAL; break;
- case R_X86_64_TLSGD: tls_type = GOT_TLS_GD; break;
- case R_X86_64_GOTTPOFF: tls_type = GOT_TLS_IE; break;
+ default:
+ tls_type = GOT_NORMAL;
+ if (h)
+ {
+ if (bfd_is_abs_symbol (&h->root))
+ tls_type = GOT_ABS;
+ }
+ else if (isym->st_shndx == SHN_ABS)
+ tls_type = GOT_ABS;
+ break;
+ case R_X86_64_TLSGD:
+ tls_type = GOT_TLS_GD;
+ break;
+ case R_X86_64_GOTTPOFF:
+ tls_type = GOT_TLS_IE;
+ break;
case R_X86_64_GOTPC32_TLSDESC:
case R_X86_64_TLSDESC_CALL:
- tls_type = GOT_TLS_GDESC; break;
+ tls_type = GOT_TLS_GDESC;
+ break;
}
if (h != NULL)
@@ -2245,8 +2292,9 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
size_reloc = FALSE;
do_size:
- if (NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type,
- htab->pointer_r_type))
+ if (!no_dynreloc
+ && NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type,
+ htab->pointer_r_type))
{
struct elf_dyn_relocs *p;
struct elf_dyn_relocs **head;
@@ -2880,7 +2928,14 @@ elf_x86_64_relocate_section (bfd *output_bfd,
base_got->contents + off);
local_got_offsets[r_symndx] |= 1;
- if (bfd_link_pic (info))
+ /* NB: GOTPCREL relocations against local absolute
+ symbol store relocation value in the GOT slot
+ without relative relocation. */
+ if (bfd_link_pic (info)
+ && !(sym->st_shndx == SHN_ABS
+ && (r_type == R_X86_64_GOTPCREL
+ || r_type == R_X86_64_GOTPCRELX
+ || r_type == R_X86_64_REX_GOTPCRELX)))
relative_reloc = TRUE;
}
}
@@ -3175,7 +3230,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
&& (X86_PCREL_TYPE_P (r_type)
|| X86_SIZE_TYPE_P (r_type)));
- if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type,
+ if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, sec,
need_copy_reloc_in_pie,
resolved_to_zero, FALSE))
{
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 108e04a158..34c78577ef 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -347,7 +347,8 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
(but if both R_386_TLS_IE_32 and R_386_TLS_IE is present, we
need two), R_386_TLS_GD and R_X86_64_TLSGD need one if local
symbol and two if global. No dynamic relocation against
- resolved undefined weak symbol in executable. */
+ resolved undefined weak symbol in executable. No dynamic
+ relocation against non-preemptible absolute symbol. */
if (tls_type == GOT_TLS_IE_BOTH)
htab->elf.srelgot->size += 2 * htab->sizeof_reloc;
else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1)
@@ -359,7 +360,9 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
&& ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
&& !resolved_to_zero)
|| h->root.type != bfd_link_hash_undefweak)
- && (bfd_link_pic (info)
+ && ((bfd_link_pic (info)
+ && !(h->dynindx == -1
+ && bfd_is_abs_symbol (&h->root)))
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
htab->elf.srelgot->size += htab->sizeof_reloc;
if (GOT_TLS_GDESC_P (tls_type))
@@ -952,6 +955,100 @@ _bfd_x86_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
return _bfd_elf_link_check_relocs (abfd, info);
}
+bfd_boolean
+_bfd_elf_x86_valid_reloc_p (asection *input_section,
+ struct bfd_link_info *info,
+ struct elf_x86_link_hash_table *htab,
+ const Elf_Internal_Rela *rel,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym,
+ Elf_Internal_Shdr *symtab_hdr,
+ bfd_boolean *no_dynreloc_p)
+{
+ bfd_boolean valid_p = TRUE;
+
+ *no_dynreloc_p = FALSE;
+
+ /* Check If relocation against non-preemptible absolute symbol is
+ valid in PIC. FIXME: Can't use SYMBOL_REFERENCES_LOCAL_P since
+ it may call _bfd_elf_link_hide_sym_by_version and result in
+ ld-elfvers/ vers21 test failure. */
+ if (bfd_link_pic (info)
+ && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, h)))
+ {
+ const struct elf_backend_data *bed;
+ unsigned int r_type;
+ Elf_Internal_Rela irel;
+
+ /* Skip non-absolute symbol. */
+ if (h)
+ {
+ if (!bfd_is_abs_symbol (&h->root))
+ return valid_p;
+ }
+ else if (sym->st_shndx != SHN_ABS)
+ return valid_p;
+
+ bed = get_elf_backend_data (input_section->owner);
+ r_type = ELF32_R_TYPE (rel->r_info);
+ irel = *rel;
+
+ /* Only allow relocations against absolute symbol, which can be
+ resolved as absolute value + addend. GOTPCREL relocations
+ are allowed since absolute value + addend is stored in the
+ GOT slot. */
+ if (bed->target_id == X86_64_ELF_DATA)
+ {
+ r_type &= ~R_X86_64_converted_reloc_bit;
+ valid_p = (r_type == R_X86_64_64
+ || r_type == R_X86_64_32
+ || r_type == R_X86_64_32S
+ || r_type == R_X86_64_16
+ || r_type == R_X86_64_8
+ || r_type == R_X86_64_GOTPCREL
+ || r_type == R_X86_64_GOTPCRELX
+ || r_type == R_X86_64_REX_GOTPCRELX);
+ if (!valid_p)
+ {
+ unsigned int r_symndx = htab->r_sym (rel->r_info);
+ irel.r_info = htab->r_info (r_symndx, r_type);
+ }
+ }
+ else
+ valid_p = (r_type == R_386_32
+ || r_type == R_386_16
+ || r_type == R_386_8);
+
+ if (valid_p)
+ *no_dynreloc_p = TRUE;
+ else
+ {
+ const char *name;
+ arelent internal_reloc;
+
+ if (!bed->elf_info_to_howto (input_section->owner,
+ &internal_reloc, &irel)
+ || internal_reloc.howto == NULL)
+ abort ();
+
+ if (h)
+ name = h->root.root.string;
+ else
+ name = bfd_elf_sym_name (input_section->owner, symtab_hdr,
+ sym, NULL);
+ info->callbacks->einfo
+ /* xgettext:c-format */
+ (_("%F%P: %pB: relocation %s against absolute symbol "
+ "`%s' in section `%pA' is disallowed\n"),
+ input_section->owner, internal_reloc.howto->name, name,
+ input_section);
+ bfd_set_error (bfd_error_bad_value);
+ }
+ }
+
+ return valid_p;
+}
+
/* Set the sizes of the dynamic sections. */
bfd_boolean
@@ -1065,7 +1162,7 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
|| *local_tls_type == GOT_TLS_IE_BOTH)
s->size += htab->got_entry_size;
}
- if (bfd_link_pic (info)
+ if ((bfd_link_pic (info) && *local_tls_type != GOT_ABS)
|| GOT_TLS_GD_ANY_P (*local_tls_type)
|| (*local_tls_type & GOT_TLS_IE))
{
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index bef17dc2ba..1841ddbc88 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -119,11 +119,15 @@
Copy dynamic function pointer relocations. Don't generate dynamic
relocations against resolved undefined weak symbols in PIE, except
when PC32_RELOC is TRUE. Undefined weak symbol is bound locally
- when PIC is false. */
-#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, \
+ when PIC is false. Don't generate dynamic relocations against
+ non-preemptible absolute symbol. */
+#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, SEC, \
NEED_COPY_RELOC_IN_PIE, \
RESOLVED_TO_ZERO, PC32_RELOC) \
((bfd_link_pic (INFO) \
+ && !(bfd_is_abs_section (SEC) \
+ && ((EH) == NULL \
+ || SYMBOL_REFERENCES_LOCAL (INFO, &(EH)->elf))) \
&& !(NEED_COPY_RELOC_IN_PIE) \
&& ((EH) == NULL \
|| ((ELF_ST_VISIBILITY ((EH)->elf.other) == STV_DEFAULT \
@@ -175,12 +179,14 @@
problem when "time" or "times" is defined as a variable in an
executable, clashing with functions of the same name in libc. If a
symbol isn't undefined weak symbol, don't make it dynamic in PIC and
- generate relative relocation. */
+ generate relative relocation. Don't generate relative relocation
+ against non-preemptible absolute symbol. */
#define GENERATE_RELATIVE_RELOC_P(INFO, H) \
((H)->dynindx == -1 \
&& !(H)->forced_local \
&& (H)->root.type != bfd_link_hash_undefweak \
- && bfd_link_pic (INFO))
+ && bfd_link_pic (INFO) \
+ && !bfd_is_abs_symbol (&(H)->root))
/* TRUE if this is a pointer reference to a local IFUNC. */
#define POINTER_LOCAL_IFUNC_P(INFO, H) \
@@ -414,6 +420,7 @@ struct elf_x86_plt_layout
#define GOT_TLS_IE_NEG 6
#define GOT_TLS_IE_BOTH 7
#define GOT_TLS_GDESC 8
+#define GOT_ABS 9
#define GOT_TLS_GD_BOTH_P(type) \
((type) == (GOT_TLS_GD | GOT_TLS_GDESC))
#define GOT_TLS_GD_P(type) \
@@ -601,6 +608,9 @@ struct elf_x86_plt
long count;
};
+/* Set if a relocation is converted from a GOTPCREL relocation. */
+#define R_X86_64_converted_reloc_bit (1 << 7)
+
#define elf_x86_tdata(abfd) \
((struct elf_x86_obj_tdata *) (abfd)->tdata.any)
@@ -652,6 +662,11 @@ extern int _bfd_x86_elf_compare_relocs
extern bfd_boolean _bfd_x86_elf_link_check_relocs
(bfd *, struct bfd_link_info *);
+extern bfd_boolean _bfd_elf_x86_valid_reloc_p
+ (asection *, struct bfd_link_info *, struct elf_x86_link_hash_table *,
+ const Elf_Internal_Rela *, struct elf_link_hash_entry *,
+ Elf_Internal_Sym *, Elf_Internal_Shdr *, bfd_boolean *);
+
extern bfd_boolean _bfd_x86_elf_size_dynamic_sections
(bfd *, struct bfd_link_info *);
diff --git a/ld/testsuite/ld-elf/linux-x86.exp b/ld/testsuite/ld-elf/linux-x86.exp
index 63a321b966..ae278a004c 100644
--- a/ld/testsuite/ld-elf/linux-x86.exp
+++ b/ld/testsuite/ld-elf/linux-x86.exp
@@ -115,3 +115,167 @@ 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-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 0000000000..5b37af08c6
--- /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 0000000000..775623b8c9
--- /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 0000000000..f02a408700
--- /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 0000000000..bb389172f1
--- /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 0000000000..f2847d7f62
--- /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-2.c b/ld/testsuite/ld-elf/pr25749-2.c
new file mode 100644
index 0000000000..820bebc167
--- /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 0000000000..df486fe329
--- /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 0000000000..ba82c450bc
--- /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 0000000000..fbc68bf268
--- /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 0000000000..2b048ec09b
--- /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 0000000000..99d585d6b5
--- /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 0000000000..7c9f58116e
--- /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 0000000000..9cab99303e
--- /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 0000000000..2d4f02abe5
--- /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 0000000000..aad3e45e0f
--- /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 0000000000..e2c2f8d54d
--- /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 0000000000..448406dff8
--- /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 0000000000..de450fe081
--- /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 0000000000..cb791dd56f
--- /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 0000000000..2923c32ee9
--- /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 0000000000..0195f19165
--- /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 0000000000..59633a3b4d
--- /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 0000000000..2532480e5f
--- /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 3c011d9b05..b340287f48 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
--
2.25.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* V6 [PATCH] x86: Only allow S - A relocations against absolute symbol
2020-04-01 14:06 ` V5 " H.J. Lu
@ 2020-04-01 21:28 ` H.J. Lu
2020-04-02 3:24 ` Alan Modra
0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2020-04-01 21:28 UTC (permalink / raw)
To: Fangrui Song; +Cc: H.J. Lu via Binutils
[-- Attachment #1: Type: text/plain, Size: 2223 bytes --]
On Wed, Apr 1, 2020 at 7:06 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, Mar 31, 2020 at 8:30 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Tue, Mar 31, 2020 at 4:25 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > On Tue, Mar 31, 2020 at 7:31 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > >
> > > > On Mon, Mar 30, 2020 at 11:18 PM Fangrui Song <i@maskray.me> wrote:
> > > > >
> > > > > On 2020-03-30, H.J. Lu via Binutils wrote:
> > > > > >Since value of non-preemptible absolute symbol (SHN_ABS) won't change,
> > > > > >only S - A relocations against non-preemptible absolute symbol are
> > > > > >allowed in PIE and shared library.
> > > > >
> > > > > Thanks for the patch. At some point we should define some generic
> > > > > relocation categories (https://reviews.llvm.org/rL266158). For example,
> > > > >
> > > > > - R_ABS: R_X86_64_8, R_X86_64_16, R_X86_64_32, R_X86_64_64
> > > > > R_AARCH64_ABS16, R_AARCH64_ABS32, R_AARCH64_ABS64
> > > > > R_PPC64_ADDR16, R_PPC64_ADDR16_DS, R_PPC64_ADDR16_HA, ...
> > > > > - R_PCREL: R_X86_64_PC8, R_X86_64_PC16, R_X86_64_PC32, R_X86_64_PC64
> > > > > R_AARCH64_PREL16, R_AARCH64_PREL32, R_AARCH64_PREL64
> > > > > - R_PLT_PCREL: R_X86_64_PLT32, R_AARCH64_CALL26
> > > > > - R_GOT_PCREL: R_X86_64_GOTPCREL, R_X86_64_GOTPCRELX
> > > > >
> > > > > Define a property is_preemptible as a more appropriate level of
> > > > > abstraction for GENERATE_DYNAMIC_RELOCATION_P and some use cases of bfd_link_pic and bfd_link_executable...
> > > >
> > > > Current BFD linker delegates most, if not all, of relocation to each backend.
> > > > There are many similar codes in backends. I am sharing as much codes
> > > > between i386 and x86-64 backends as I can.
> > > >
> > > > This is the patch I am checking in.
> > >
> > > Here is the updated patch to include the fix for
> > >
> > > https://sourceware.org/bugzilla/show_bug.cgi?id=25754
> > >
> >
> > Another update to allow GOTPCREL relocations.
>
> Update to detect R_X86_64_32S/R_X86_64_32 overflow.
>
This is the final version I am checking in. It allows PC relocation
against absolute
symbols defined by linker script. Tested with GCC, glibc and Linux
x86-64 kernel.
--
H.J.
[-- Attachment #2: 0001-x86-Only-allow-S-A-relocations-against-absolute-symb.patch --]
[-- Type: application/x-patch, Size: 41066 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: V6 [PATCH] x86: Only allow S - A relocations against absolute symbol
2020-04-01 21:28 ` V6 " H.J. Lu
@ 2020-04-02 3:24 ` Alan Modra
2020-04-02 11:54 ` H.J. Lu
0 siblings, 1 reply; 10+ messages in thread
From: Alan Modra @ 2020-04-02 3:24 UTC (permalink / raw)
To: H.J. Lu; +Cc: binutils
Seen here on Ubuntu 18.04 when using a number of different gcc
versions.
FAIL: Run pr25749-1bb (-no-pie -fno-PIE)
FAIL: Run pr25749-1bb (-pie -fPIE)
FAIL: Run pr25749-2ab (-no-pie -fno-PIE)
FAIL: Run pr25749-2ab (-pie -fPIE)
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: V6 [PATCH] x86: Only allow S - A relocations against absolute symbol
2020-04-02 3:24 ` Alan Modra
@ 2020-04-02 11:54 ` H.J. Lu
2020-04-02 14:10 ` H.J. Lu
0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2020-04-02 11:54 UTC (permalink / raw)
To: Alan Modra; +Cc: Binutils
On Wed, Apr 1, 2020 at 8:25 PM Alan Modra <amodra@gmail.com> wrote:
>
> Seen here on Ubuntu 18.04 when using a number of different gcc
> versions.
>
> FAIL: Run pr25749-1bb (-no-pie -fno-PIE)
> FAIL: Run pr25749-1bb (-pie -fPIE)
> FAIL: Run pr25749-2ab (-no-pie -fno-PIE)
> FAIL: Run pr25749-2ab (-pie -fPIE)
Ubuntu 18.04 has glibc 2.27 which doesn't have
commit e7feec374c635b6a29d65c39ae5e1855528fed39
Author: Maciej W. Rozycki <macro@mips.com>
Date: Wed Apr 4 23:09:37 2018 +0100
elf: Correct absolute (SHN_ABS) symbol run-time calculation [BZ #19818]
Do not relocate absolute symbols by the base address. Such symbols have
SHN_ABS as the section index and their value is not supposed to be
affected by relocation as per the ELF gABI[1]:
"SHN_ABS
The symbol has an absolute value that will not change because of
relocation."
Glibc 2.28 and above are OK.
--
H.J.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: V6 [PATCH] x86: Only allow S - A relocations against absolute symbol
2020-04-02 11:54 ` H.J. Lu
@ 2020-04-02 14:10 ` H.J. Lu
0 siblings, 0 replies; 10+ messages in thread
From: H.J. Lu @ 2020-04-02 14:10 UTC (permalink / raw)
To: Alan Modra; +Cc: Binutils
On Thu, Apr 2, 2020 at 4:54 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Wed, Apr 1, 2020 at 8:25 PM Alan Modra <amodra@gmail.com> wrote:
> >
> > Seen here on Ubuntu 18.04 when using a number of different gcc
> > versions.
> >
> > FAIL: Run pr25749-1bb (-no-pie -fno-PIE)
> > FAIL: Run pr25749-1bb (-pie -fPIE)
> > FAIL: Run pr25749-2ab (-no-pie -fno-PIE)
> > FAIL: Run pr25749-2ab (-pie -fPIE)
>
> Ubuntu 18.04 has glibc 2.27 which doesn't have
>
> commit e7feec374c635b6a29d65c39ae5e1855528fed39
> Author: Maciej W. Rozycki <macro@mips.com>
> Date: Wed Apr 4 23:09:37 2018 +0100
>
> elf: Correct absolute (SHN_ABS) symbol run-time calculation [BZ #19818]
>
> Do not relocate absolute symbols by the base address. Such symbols have
> SHN_ABS as the section index and their value is not supposed to be
> affected by relocation as per the ELF gABI[1]:
>
> "SHN_ABS
> The symbol has an absolute value that will not change because of
> relocation."
>
> Glibc 2.28 and above are OK.
>
These tests are OK on Ubuntu 20.04.
--
H.J.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2020-04-02 14:11 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-31 4:43 [PATCH] x86: Only allow S - A relocations against absolute symbol H.J. Lu
2020-03-31 6:17 ` Fangrui Song
2020-03-31 14:31 ` H.J. Lu
2020-03-31 23:25 ` V3 " H.J. Lu
2020-04-01 3:30 ` V4 " H.J. Lu
2020-04-01 14:06 ` V5 " H.J. Lu
2020-04-01 21:28 ` V6 " H.J. Lu
2020-04-02 3:24 ` Alan Modra
2020-04-02 11:54 ` H.J. Lu
2020-04-02 14:10 ` H.J. Lu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).