[PATCH] ld: Add -z no-relax=SYMBOL
H.J. Lu
hjl.tools@gmail.com
Mon Jan 27 01:33:30 GMT 2025
Add a "-z no-relax=SYMBOL" option to x86-64 linker to disable linker
optimization on GOTPCRELX relocations against SYMBOL.
bfd/
PR ld/32591
* elf-linker-x86.h (_bfd_elf_linker_x86_no_relax_symbol): New.
* elf64-x86-64.c (elf_x86_64_convert_load_reloc): Avoid relocation
overflow if a symbol is in no_relax_htab.
(elf_x86_64_relocate_section): Don't warn GOTPCREL more than once
for a symbol. Replace --no-relax with -z no-relax=SYMBOL for
GOTPCREL conversion overflow.
* elfxx-x86.c: Include sysdep.h and libiberty.h.
(_bfd_x86_elf_finish_dynamic_sections): Free no_relax_htab.
(_bfd_elf_linker_x86_set_options): If --no-relax is used, free
no_relax_htab.
(_bfd_elf_linker_x86_no_relax_symbol): New.
include/
PR ld/32591
* bfdlink.h (bfd_link_info): Add no_relax_htab for the hash table
for symbols without relaxation.
ld/
PR ld/32591
* NEWS: Mention "-z no-relax=SYMBOL".
* ld.texi: Document "-z no-relax=SYMBOL".
* emulparams/elf32_x86_64.sh: Source x86-64-no-relax.sh.
* emulparams/elf_x86_64.sh: Likewise.
* emulparams/x86-64-no-relax.sh: New file.
* testsuite/ld-x86-64/pr19609-2a.d: Updated.
* testsuite/ld-x86-64/pr19609-2b.d: Likewise.
* testsuite/ld-x86-64/pr19609-4a.d: Likewise.
* testsuite/ld-x86-64/pr19609-4c.d: Likewise.
* testsuite/ld-x86-64/pr19609-5d.d: Likewise.
* testsuite/ld-x86-64/pr19609-7a.d: Likewise.
* testsuite/ld-x86-64/pr19609-7c.d: Likewise.
* testsuite/ld-x86-64/pr32591-x32.d: New file.
* testsuite/ld-x86-64/pr32591.d: Likewise.
* testsuite/ld-x86-64/pr32591.s: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run PR ld/32591 tests.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
bfd/elf-linker-x86.h | 2 ++
bfd/elf64-x86-64.c | 27 +++++++++++++++++++++++++--
bfd/elfxx-x86.c | 26 ++++++++++++++++++++++++++
include/bfdlink.h | 3 +++
ld/NEWS | 3 +++
ld/emulparams/elf32_x86_64.sh | 1 +
ld/emulparams/elf_x86_64.sh | 1 +
ld/emulparams/x86-64-no-relax.sh | 12 ++++++++++++
ld/ld.texi | 5 +++++
ld/testsuite/ld-x86-64/pr19609-2a.d | 2 +-
ld/testsuite/ld-x86-64/pr19609-2b.d | 2 +-
ld/testsuite/ld-x86-64/pr19609-4a.d | 2 +-
ld/testsuite/ld-x86-64/pr19609-4c.d | 2 +-
ld/testsuite/ld-x86-64/pr19609-5d.d | 2 +-
ld/testsuite/ld-x86-64/pr19609-7a.d | 2 +-
ld/testsuite/ld-x86-64/pr19609-7c.d | 2 +-
ld/testsuite/ld-x86-64/pr32591-x32.d | 13 +++++++++++++
ld/testsuite/ld-x86-64/pr32591.d | 13 +++++++++++++
ld/testsuite/ld-x86-64/pr32591.s | 13 +++++++++++++
ld/testsuite/ld-x86-64/x86-64.exp | 2 ++
20 files changed, 126 insertions(+), 9 deletions(-)
create mode 100644 ld/emulparams/x86-64-no-relax.sh
create mode 100644 ld/testsuite/ld-x86-64/pr32591-x32.d
create mode 100644 ld/testsuite/ld-x86-64/pr32591.d
create mode 100644 ld/testsuite/ld-x86-64/pr32591.s
diff --git a/bfd/elf-linker-x86.h b/bfd/elf-linker-x86.h
index 2c98257038f..eef5cbb4352 100644
--- a/bfd/elf-linker-x86.h
+++ b/bfd/elf-linker-x86.h
@@ -93,3 +93,5 @@ struct elf_linker_x86_params
extern void _bfd_elf_linker_x86_set_options
(struct bfd_link_info *, struct elf_linker_x86_params *);
+extern void _bfd_elf_linker_x86_no_relax_symbol
+ (struct bfd_link_info *, const char *);
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index d1d02bd7b32..78dfd7d4385 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1898,6 +1898,16 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
if (isym->st_shndx == SHN_UNDEF)
return true;
+ if (link_info->no_relax_htab != NULL)
+ {
+ const char *name = bfd_elf_sym_name (abfd,
+ &elf_symtab_hdr (abfd),
+ isym, NULL);
+ if (htab_find (link_info->no_relax_htab, name)
+ != HTAB_EMPTY_ENTRY)
+ no_overflow = true;
+ }
+
local_ref = true;
if (isym->st_shndx == SHN_ABS)
{
@@ -1922,6 +1932,11 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
R_X86_64_PC32. */
struct elf_x86_link_hash_entry *eh = elf_x86_hash_entry (h);
+ if (link_info->no_relax_htab != NULL
+ && (htab_find (link_info->no_relax_htab, h->root.root.string)
+ != HTAB_EMPTY_ENTRY))
+ no_overflow = true;
+
abs_symbol = ABS_SYMBOL_P (h);
abs_relocation = h->root.u.def.value;
@@ -4879,12 +4894,20 @@ elf_x86_64_relocate_section (bfd *output_bfd,
{
if (converted_reloc)
{
+ if (info->no_relax_htab != NULL
+ && (htab_find (info->no_relax_htab, name)
+ != HTAB_EMPTY_ENTRY))
+ continue;
+
+ /* Don't warn GOTPCREL more than once for a symbol. */
+ _bfd_elf_linker_x86_no_relax_symbol (info, name);
+
info->callbacks->einfo
("%X%H:", input_bfd, input_section, rel->r_offset);
info->callbacks->einfo
(_(" failed to convert GOTPCREL relocation against "
- "'%s'; relink with --no-relax\n"),
- name);
+ "'%s'; relink with -z no-relax=%s\n"),
+ name, name);
status = false;
continue;
}
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 8e5a005fd36..a6d6894d887 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -18,6 +18,8 @@
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
+#include "sysdep.h"
+#include "libiberty.h"
#include "elfxx-x86.h"
#include "elf-vxworks.h"
#include "objalloc.h"
@@ -2756,6 +2758,12 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
bfd_byte *dyncon, *dynconend;
bfd_size_type sizeof_dyn;
+ if (info->no_relax_htab != NULL)
+ {
+ htab_delete (info->no_relax_htab);
+ info->no_relax_htab = NULL;
+ }
+
bed = get_elf_backend_data (output_bfd);
htab = elf_x86_hash_table (info, bed->target_id);
if (htab == NULL)
@@ -4950,4 +4958,22 @@ _bfd_elf_linker_x86_set_options (struct bfd_link_info * info,
= elf_x86_hash_table (info, bed->target_id);
if (htab != NULL)
htab->params = params;
+ /* If --no-relax is used, free no_relax_htab. */
+ if (info->disable_target_specific_optimizations > 1
+ && info->no_relax_htab != NULL)
+ {
+ htab_delete (info->no_relax_htab);
+ info->no_relax_htab = NULL;
+ }
+}
+
+void
+_bfd_elf_linker_x86_no_relax_symbol (struct bfd_link_info *info,
+ const char *name)
+{
+ if (info->no_relax_htab == NULL)
+ info->no_relax_htab = htab_create_alloc (16, htab_hash_string,
+ htab_eq_string, NULL,
+ xcalloc, free);
+ *htab_find_slot (info->no_relax_htab, name, INSERT) = (char *) name;
}
diff --git a/include/bfdlink.h b/include/bfdlink.h
index ae451075996..da60a271f69 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -759,6 +759,9 @@ struct bfd_link_info
/* The version information. */
struct bfd_elf_version_tree *version_info;
+ /* The hash table for symbols without relaxation. */
+ void *no_relax_htab;
+
/* Size of cache. Backend can use it to keep strace cache size. */
bfd_size_type cache_size;
diff --git a/ld/NEWS b/ld/NEWS
index 17fb20a6b9f..ca242e9b62d 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
-*- text -*-
+* Add a "-z no-relax=SYMBOL" option to x86-64 linker to disable linker
+ optimization on GOTPCRELX relocations against SYMBOL.
+
Changes in 2.44:
* Support for Nios II target has been removed, as this architecture has been
diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh
index 6a92eec129d..3d9242d0d27 100644
--- a/ld/emulparams/elf32_x86_64.sh
+++ b/ld/emulparams/elf32_x86_64.sh
@@ -8,6 +8,7 @@ source_sh ${srcdir}/emulparams/x86-report-relative.sh
source_sh ${srcdir}/emulparams/x86-64-level.sh
source_sh ${srcdir}/emulparams/x86-64-level-report.sh
source_sh ${srcdir}/emulparams/x86-64-plt.sh
+source_sh ${srcdir}/emulparams/x86-64-no-relax.sh
source_sh ${srcdir}/emulparams/static.sh
source_sh ${srcdir}/emulparams/dt-relr.sh
SCRIPT_NAME=elf
diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh
index 92449745c7a..dc0cbdd9da1 100644
--- a/ld/emulparams/elf_x86_64.sh
+++ b/ld/emulparams/elf_x86_64.sh
@@ -9,6 +9,7 @@ source_sh ${srcdir}/emulparams/x86-64-level.sh
source_sh ${srcdir}/emulparams/x86-64-level-report.sh
source_sh ${srcdir}/emulparams/x86-64-lam.sh
source_sh ${srcdir}/emulparams/x86-64-plt.sh
+source_sh ${srcdir}/emulparams/x86-64-no-relax.sh
source_sh ${srcdir}/emulparams/static.sh
source_sh ${srcdir}/emulparams/dt-relr.sh
SCRIPT_NAME=elf
diff --git a/ld/emulparams/x86-64-no-relax.sh b/ld/emulparams/x86-64-no-relax.sh
new file mode 100644
index 00000000000..411a3c21833
--- /dev/null
+++ b/ld/emulparams/x86-64-no-relax.sh
@@ -0,0 +1,12 @@
+PARSE_AND_LIST_OPTIONS_X86_64_NO_RELAX='
+ fprintf (file, _("\
+ -z no-relax=SYMBOL Do not use relaxation on SYMBOL\n"));
+'
+PARSE_AND_LIST_ARGS_CASE_Z_X86_64_NO_RELAX='
+ else if (startswith (optarg, "no-relax="))
+ _bfd_elf_linker_x86_no_relax_symbol (&link_info,
+ optarg + 9);
+'
+
+PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_X86_64_NO_RELAX"
+PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_X86_64_NO_RELAX"
diff --git a/ld/ld.texi b/ld/ld.texi
index f6384ad82dd..7e6648f93a2 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -1569,6 +1569,11 @@ Supported for x86_64.
@item muldefs
Allow multiple definitions.
+@item no-relax=@var{symbol}
+Disable linker optimization on GOTPCRELX relocations against @var{symbol}.
+This option may be used multiple times on the command line to disable
+linker optimization against multiple symbols. Supported for x86_64.
+
@item nocopyreloc
Disable linker generated .dynbss variables used in place of variables
defined in shared libraries. May result in dynamic text relocations.
diff --git a/ld/testsuite/ld-x86-64/pr19609-2a.d b/ld/testsuite/ld-x86-64/pr19609-2a.d
index 6d3db92afb7..de559775f15 100644
--- a/ld/testsuite/ld-x86-64/pr19609-2a.d
+++ b/ld/testsuite/ld-x86-64/pr19609-2a.d
@@ -1,4 +1,4 @@
#source: pr19609-2.s
#as: --64 -mrelax-relocations=yes
#ld: -melf_x86_64 -Ttext=0x70000000 -Tdata=0xa0000000
-#error: .*failed to convert GOTPCREL relocation against 'foo'; relink with --no-relax.*
+#error: .*failed to convert GOTPCREL relocation against 'foo'; relink with -z no-relax=foo
diff --git a/ld/testsuite/ld-x86-64/pr19609-2b.d b/ld/testsuite/ld-x86-64/pr19609-2b.d
index 4fee93d7034..42870295d04 100644
--- a/ld/testsuite/ld-x86-64/pr19609-2b.d
+++ b/ld/testsuite/ld-x86-64/pr19609-2b.d
@@ -1,4 +1,4 @@
#source: pr19609-2.s
#as: --x32 -mrelax-relocations=yes
#ld: -melf32_x86_64 -Ttext=0x70000000 -Tdata=0xa0000000
-#error: .*failed to convert GOTPCREL relocation against 'foo'; relink with --no-relax.*
+#error: .*failed to convert GOTPCREL relocation against 'foo'; relink with -z no-relax=foo
diff --git a/ld/testsuite/ld-x86-64/pr19609-4a.d b/ld/testsuite/ld-x86-64/pr19609-4a.d
index eb37d0c8729..931b2b7d109 100644
--- a/ld/testsuite/ld-x86-64/pr19609-4a.d
+++ b/ld/testsuite/ld-x86-64/pr19609-4a.d
@@ -1,4 +1,4 @@
#source: pr19609-4.s
#as: --64 -mrelax-relocations=yes
#ld: -melf_x86_64 -Ttext=0x70000000 -Tdata=0xa0000000
-#error: .*failed to convert GOTPCREL relocation against 'foo'; relink with --no-relax.*failed to convert GOTPCREL relocation against 'foo'; relink with --no-relax.*
+#error: .*failed to convert GOTPCREL relocation against 'foo'; relink with -z no-relax=foo
diff --git a/ld/testsuite/ld-x86-64/pr19609-4c.d b/ld/testsuite/ld-x86-64/pr19609-4c.d
index eb37d0c8729..931b2b7d109 100644
--- a/ld/testsuite/ld-x86-64/pr19609-4c.d
+++ b/ld/testsuite/ld-x86-64/pr19609-4c.d
@@ -1,4 +1,4 @@
#source: pr19609-4.s
#as: --64 -mrelax-relocations=yes
#ld: -melf_x86_64 -Ttext=0x70000000 -Tdata=0xa0000000
-#error: .*failed to convert GOTPCREL relocation against 'foo'; relink with --no-relax.*failed to convert GOTPCREL relocation against 'foo'; relink with --no-relax.*
+#error: .*failed to convert GOTPCREL relocation against 'foo'; relink with -z no-relax=foo
diff --git a/ld/testsuite/ld-x86-64/pr19609-5d.d b/ld/testsuite/ld-x86-64/pr19609-5d.d
index 0ab28efff1e..9fe54b130a3 100644
--- a/ld/testsuite/ld-x86-64/pr19609-5d.d
+++ b/ld/testsuite/ld-x86-64/pr19609-5d.d
@@ -1,4 +1,4 @@
#source: pr19609-5.s
#as: --64 -mrelax-relocations=yes
#ld: -melf_x86_64 -Ttext=0x80000000
-#error: .*failed to convert GOTPCREL relocation against 'bar'; relink with --no-relax
+#error: .*failed to convert GOTPCREL relocation against 'bar'; relink with -z no-relax=bar
diff --git a/ld/testsuite/ld-x86-64/pr19609-7a.d b/ld/testsuite/ld-x86-64/pr19609-7a.d
index 34704a94c16..c1fe8b6f804 100644
--- a/ld/testsuite/ld-x86-64/pr19609-7a.d
+++ b/ld/testsuite/ld-x86-64/pr19609-7a.d
@@ -1,4 +1,4 @@
#source: pr19609-7.s
#as: --64 -mrelax-relocations=yes
#ld: -melf_x86_64 -Ttext=0x80000000
-#error: .*failed to convert GOTPCREL relocation against 'foobar'; relink with --no-relax
+#error: .*failed to convert GOTPCREL relocation against 'foobar'; relink with -z no-relax=foobar
diff --git a/ld/testsuite/ld-x86-64/pr19609-7c.d b/ld/testsuite/ld-x86-64/pr19609-7c.d
index 09488e22a8e..add0d5cbabe 100644
--- a/ld/testsuite/ld-x86-64/pr19609-7c.d
+++ b/ld/testsuite/ld-x86-64/pr19609-7c.d
@@ -1,4 +1,4 @@
#source: pr19609-7.s
#as: --x32 -mrelax-relocations=yes
#ld: -melf32_x86_64 -Ttext=0x80000000
-#error: .*failed to convert GOTPCREL relocation against 'foobar'; relink with --no-relax
+#error: .*failed to convert GOTPCREL relocation against 'foobar'; relink with -z no-relax=foobar
diff --git a/ld/testsuite/ld-x86-64/pr32591-x32.d b/ld/testsuite/ld-x86-64/pr32591-x32.d
new file mode 100644
index 00000000000..ae438855935
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr32591-x32.d
@@ -0,0 +1,13 @@
+#source: pr32591.s
+#as: --x32 -mrelax-relocations=yes
+#ld: -melf32_x86_64 -Ttext=0x70000000 -Tdata=0xa0000000 -z no-relax=foo -z no-relax=bar
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+70000000 <_start>:
+[ ]*[a-f0-9]+: 48 3b 05 ([0-9a-f]{2} ){4} cmp -?0x[a-f0-9]+\(%rip\),%rax # .*
+[ ]*[a-f0-9]+: 48 3b 05 ([0-9a-f]{2} ){4} cmp -?0x[a-f0-9]+\(%rip\),%rax # .*
diff --git a/ld/testsuite/ld-x86-64/pr32591.d b/ld/testsuite/ld-x86-64/pr32591.d
new file mode 100644
index 00000000000..eed53ab6565
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr32591.d
@@ -0,0 +1,13 @@
+#as: --64 -mrelax-relocations=yes
+#ld: -melf_x86_64 -Ttext=0x70000000 -Tdata=0xa0000000 -z no-relax=foo -z no-relax=bar
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+70000000 <_start>:
+[ ]*[a-f0-9]+: 48 3b 05 ([0-9a-f]{2} ){4} cmp -?0x[a-f0-9]+\(%rip\),%rax # .*
+[ ]*[a-f0-9]+: 48 3b 05 ([0-9a-f]{2} ){4} cmp -?0x[a-f0-9]+\(%rip\),%rax # .*
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr32591.s b/ld/testsuite/ld-x86-64/pr32591.s
new file mode 100644
index 00000000000..35ff57bcbf3
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr32591.s
@@ -0,0 +1,13 @@
+ .data
+foo:
+ .quad 0
+ .globl bar
+bar:
+ .quad 0
+ .text
+ .globl _start
+ .type _start, @function
+_start:
+ cmpq foo@GOTPCREL(%rip), %rax
+ cmpq bar@GOTPCREL(%rip), %rax
+ .size _start, .-_start
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 48a468814c1..46f542f329f 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -544,6 +544,8 @@ run_dump_test "tlsdesc4"
run_dump_test "tlsdesc5"
run_dump_test "pr32191"
run_dump_test "pr32191-x32"
+run_dump_test "pr32591"
+run_dump_test "pr32591-x32"
if { ![skip_sframe_tests] } {
run_dump_test "sframe-simple-1"
--
2.48.1
More information about the Binutils
mailing list