ld: Add -z no-relax=SYMBOL
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_binutils_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-arm |
success
|
Test passed
|
Commit Message
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
Comments
On Mon, Jan 27, 2025 at 9:33 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> 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.
I can make it generic if it is useful for other targets, like arm, longarch and
riscv.
> 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
>
On Sun, Jan 26, 2025 at 8:06 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Mon, Jan 27, 2025 at 9:33 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > 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.
>
> I can make it generic if it is useful for other targets, like arm, longarch and
> riscv.
>
Interesting. I added a comment
https://sourceware.org/bugzilla/show_bug.cgi?id=32591#c4
I believe we should implement a more general and robust mechanism for
reverting GOT optimization decisions, rather than relying on the
ad-hoc -z no-relax= linker option.
With my experience on large x86-64 executables, -z no-relax= could be
cumbersome as there can be many symbols unreachable to their GOT
entries.
R_390_GOTENT for s390x is similar. The lld port handles it as well.
I think in RISC-V and LoongArch, --no-relax indicates linker
relaxation, which has sophisticated address dependent computation
doesn't need the -z no-relax= workaround.
(It seems that the term "linker optimization" is often used when the
number of bytes does not change (AArch64, PPC, x86-64, etc) while
"linker relaxation" is used when the number of bytes decreases
(RISC-V, LoongArch).)
On 27.01.2025 02:33, H.J. Lu wrote:
> Add a "-z no-relax=SYMBOL" option to x86-64 linker to disable linker
> optimization on GOTPCRELX relocations against SYMBOL.
If I'm not mistaken, this addresses only one of the two aspects mentioned
in the bug report: While it indeed makes -z no-relax more fine grained, it
at the same time still is all-or-nothing for a particular symbol. When, as
described there, the conversion to PC32 may be okay to make (as that's
merely dependent on executable size, not on its load address). Obviously
the situation can in principle also be the other way around: Conversion to
PC32 may not be possible, but conversion to 32/32S may be.
I continue to think along the lines of what Fangrui also said: We rather
need to be able to roll back (unless we can arrange for deferring the
decision until a point where we know whether the converted-to relocation
would overflow).
Jan
@@ -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 *);
@@ -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;
}
@@ -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;
}
@@ -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;
@@ -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
@@ -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
@@ -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
new file mode 100644
@@ -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"
@@ -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.
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
new file mode 100644
@@ -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 # .*
new file mode 100644
@@ -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
new file mode 100644
@@ -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
@@ -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"