public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/10] ld: Implement DT_RELR for x86
@ 2022-01-07 19:06 H.J. Lu
  2022-01-07 19:06 ` [PATCH 01/10] ld: Extract _bfd_elf_link_iterate_on_relocs H.J. Lu
                   ` (10 more replies)
  0 siblings, 11 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-07 19:06 UTC (permalink / raw)
  To: binutils; +Cc: Nick Clifton, Alan Modra, libc-alpha

Hi Nick,

I'd like to enable DT_RELR for x86 in binutils 2.38.


H.J.
---
DT_RELR encodes consecutive R_*_RELATIVE relocations in GOT (the global
offset table) and data sections in a compact format:

https://groups.google.com/g/generic-abi/c/bX460iggiKg

On some targets, R_*_RELATIVE relocations are counted and the GOT offsets
are allocated when setting the dynamic section sizes after seeing all
relocations.  R_*_RELATIVE relocations are generated while relocating
sections after section layout has been finalized.

To prepare for DT_RELR implementation on these targets, extract
_bfd_elf_link_iterate_on_relocs from _bfd_elf_link_check_relocs so
that a backend can scan relocations in elf_backend_always_size_sections

For x86 targets, the old check_relocs is renamed to scan_relocs and a
new check_relocs is added to chek input sections and create dynamic
relocation sections so that they will be mapped to output sections.
scan_relocs is now called from elf_backend_always_size_sections.

On some targets, the DT_RELR section size can be computed only after all
symbols addresses can be determined:

1. Update ldelf_map_segments to pass need_layout to
_bfd_elf_map_sections_to_segments which will size DT_RELR section and
set need_layout to true if the DT_RELR section size is changed.
2.  Set the preliminary DT_RELR section size before mapping sections to
segments and set the final DT_RELR section size after regular symbol
processing is done.

On x86, DT_RELR is implemented with linker relaxation:

1. During linker relaxation, we scan input relocations with the same
logic in relocate_section to determine if a relative relocation should
be generated and save the relative relocation candidate information for
sizing the DT_RELR section later after all symbols addresses can be
determined.  For these relative relocations which can't be placed in
the DT_RELR section, they will be placed in the rela.dyn/rel.dyn
section.
2. When DT_RELR is enabled, _bfd_elf_map_sections_to_segments calls a
backend function to size the DT_RELR section which will compute the
DT_RELR section size and tell ldelf_map_segments to layout sections
again when the DT_RELR section size has been increased.
3. After regular symbol processing is finished, bfd_elf_final_link calls
a backend function to finish the DT_RELR section.

When DT_RELR is enabled, to avoid random run-time crash with older glibc
binaries without DT_RELR support, add a GLIBC_ABI_DT_RELR symbol version,
which is provided by glibc with DT_RELR support, dependency on the shared
C library if it provides a GLIBC_2.XX symbol version.

It can build DT_RELR enabled glibc successfully on x86-64, x32 and
i686.

H.J. Lu (10):
  ld: Extract _bfd_elf_link_iterate_on_relocs
  elf: Add .relr.dyn to special_sections_r
  elf: Extract _bfd_elf_process_reverse_copy
  elf: Pass need_layout to _bfd_elf_map_sections_to_segments
  ld: Initial DT_RELR support
  elf: Add size_relative_relocs and finish_relative_relocs
  elf: Support DT_RELR in linker tests
  x86: Add DT_RELR support
  ld: Add simple DT_RELR tests
  ld: Add glibc dependency for DT_RELR

 bfd/elf-bfd.h                                 |   19 +-
 bfd/elf.c                                     |   22 +-
 bfd/elf32-i386.c                              |  112 +-
 bfd/elf64-x86-64.c                            |  118 +-
 bfd/elflink.c                                 |  191 ++-
 bfd/elfxx-target.h                            |    8 +
 bfd/elfxx-x86.c                               | 1022 +++++++++++++++++
 bfd/elfxx-x86.h                               |  197 +++-
 binutils/testsuite/lib/binutils-common.exp    |    1 +
 include/bfdlink.h                             |    4 +
 ld/NEWS                                       |    3 +
 ld/emulparams/dt-relr.sh                      |   21 +
 ld/emulparams/elf32_x86_64.sh                 |    1 +
 ld/emulparams/elf_i386.sh                     |    1 +
 ld/emulparams/elf_x86_64.sh                   |    1 +
 ld/emultempl/elf.em                           |    5 +-
 ld/ld.texi                                    |   16 +-
 ld/ldelf.c                                    |   13 +
 ld/ldelfgen.c                                 |    3 +-
 ld/lexsup.c                                   |    1 +
 ld/scripttempl/elf.sc                         |    4 +
 ld/testsuite/config/default.exp               |   16 +
 ld/testsuite/ld-elf/dt-relr-1.s               |   13 +
 ld/testsuite/ld-elf/dt-relr-1a.d              |   10 +
 ld/testsuite/ld-elf/dt-relr-1b.d              |    9 +
 ld/testsuite/ld-elf/dt-relr-1c.d              |    9 +
 ld/testsuite/ld-elf/dt-relr-2.s               |   20 +
 ld/testsuite/ld-elf/dt-relr-2a.d              |   10 +
 ld/testsuite/ld-elf/dt-relr-2b.d              |   17 +
 ld/testsuite/ld-elf/dt-relr-2c.d              |   17 +
 ld/testsuite/ld-elf/dt-relr-2d.d              |    9 +
 ld/testsuite/ld-elf/dt-relr-2e.d              |    9 +
 ld/testsuite/ld-elf/dt-relr-2f.d              |    8 +
 ld/testsuite/ld-elf/dt-relr-2g.d              |    9 +
 ld/testsuite/ld-elf/dt-relr-2h.d              |    9 +
 ld/testsuite/ld-elf/dt-relr-glibc-1.c         |   11 +
 ld/testsuite/ld-elf/dt-relr-glibc-1a.rd       |    4 +
 ld/testsuite/ld-elf/dt-relr-glibc-1b.rd       |    7 +
 ld/testsuite/ld-elf/dt-relr.exp               |   44 +
 ld/testsuite/ld-elf/shared.exp                |    3 +-
 ld/testsuite/ld-i386/export-class.exp         |    2 +-
 ld/testsuite/ld-i386/i386.exp                 |   20 +-
 ld/testsuite/ld-i386/ibt-plt-2a.d             |    2 +-
 ld/testsuite/ld-i386/ibt-plt-3a.d             |    2 +-
 ld/testsuite/ld-i386/ibt-plt-3c.d             |    2 +-
 ld/testsuite/ld-i386/pr27491-1a.d             |    4 +-
 ld/testsuite/ld-i386/report-reloc-1.d         |    2 +-
 ld/testsuite/ld-ifunc/ifunc-2-i386-now.d      |    2 +-
 .../ld-ifunc/ifunc-2-local-i386-now.d         |    2 +-
 .../ld-ifunc/ifunc-2-local-x86-64-now.d       |    2 +-
 ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d    |    2 +-
 ld/testsuite/ld-ifunc/pr17154-x86-64-now.d    |    2 +-
 ld/testsuite/ld-ifunc/pr17154-x86-64.d        |    2 +-
 ld/testsuite/ld-x86-64/bnd-branch-1-now.d     |    2 +-
 ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d      |    2 +-
 ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d      |    2 +-
 ld/testsuite/ld-x86-64/bnd-ifunc-2.d          |    2 +-
 ld/testsuite/ld-x86-64/bnd-plt-1-now.d        |    2 +-
 ld/testsuite/ld-x86-64/bnd-plt-1.d            |    2 +-
 ld/testsuite/ld-x86-64/export-class.exp       |    3 +-
 ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d       |    2 +-
 ld/testsuite/ld-x86-64/ibt-plt-2a.d           |    2 +-
 ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d       |    2 +-
 ld/testsuite/ld-x86-64/ibt-plt-3a.d           |    2 +-
 ld/testsuite/ld-x86-64/ilp32-4.d              |    2 +-
 ld/testsuite/ld-x86-64/load1c.d               |    2 +-
 ld/testsuite/ld-x86-64/load1d.d               |    2 +-
 ld/testsuite/ld-x86-64/pr13082-2b.d           |    2 +-
 ld/testsuite/ld-x86-64/pr14207.d              |    2 +-
 ld/testsuite/ld-x86-64/pr18176.d              |    2 +-
 ld/testsuite/ld-x86-64/pr19162.d              |    2 +-
 ld/testsuite/ld-x86-64/pr19636-2d.d           |    2 +-
 ld/testsuite/ld-x86-64/pr19636-2l.d           |    2 +-
 ld/testsuite/ld-x86-64/pr20253-1d.d           |    2 +-
 ld/testsuite/ld-x86-64/pr20253-1f.d           |    2 +-
 ld/testsuite/ld-x86-64/pr20253-1j.d           |    2 +-
 ld/testsuite/ld-x86-64/pr20253-1l.d           |    2 +-
 ld/testsuite/ld-x86-64/pr27491-1a.d           |    4 +-
 ld/testsuite/ld-x86-64/report-reloc-1-x32.d   |    2 +-
 ld/testsuite/ld-x86-64/report-reloc-1.d       |    2 +-
 ld/testsuite/ld-x86-64/x86-64.exp             |   65 +-
 81 files changed, 1931 insertions(+), 234 deletions(-)
 create mode 100644 ld/emulparams/dt-relr.sh
 create mode 100644 ld/testsuite/ld-elf/dt-relr-1.s
 create mode 100644 ld/testsuite/ld-elf/dt-relr-1a.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-1b.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-1c.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2.s
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2a.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2b.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2c.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2d.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2e.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2f.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2g.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2h.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1.c
 create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1a.rd
 create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1b.rd
 create mode 100644 ld/testsuite/ld-elf/dt-relr.exp

-- 
2.33.1


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 01/10] ld: Extract _bfd_elf_link_iterate_on_relocs
  2022-01-07 19:06 [PATCH 0/10] ld: Implement DT_RELR for x86 H.J. Lu
@ 2022-01-07 19:06 ` H.J. Lu
  2022-01-07 19:06 ` [PATCH 02/10] elf: Add .relr.dyn to special_sections_r H.J. Lu
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-07 19:06 UTC (permalink / raw)
  To: binutils; +Cc: Nick Clifton, Alan Modra, libc-alpha

DT_RELR encodes consecutive R_*_RELATIVE relocations in GOT (the global
offset table) and data sections in a compact format:

https://groups.google.com/g/generic-abi/c/bX460iggiKg

On some targets, R_*_RELATIVE relocations are counted and the GOT offsets
are allocated when setting the dynamic section sizes after seeing all
relocations.  R_*_RELATIVE relocations are generated while relocating
sections after section layout has been finalized.

To prepare for DT_RELR implementation on these targets, extract
_bfd_elf_link_iterate_on_relocs from _bfd_elf_link_check_relocs so
that a backend can scan relocations in elf_backend_always_size_sections

For x86 targets, the old check_relocs is renamed to scan_relocs and a
new check_relocs is added to chek input sections and create dynamic
relocation sections so that they will be mapped to output sections.
scan_relocs is now called from elf_backend_always_size_sections.

Since relocations are scanned after __start, __stop, .startof. and
.sizeof. symbols have been finalized on x86, __[start|stop]_SECNAME for
--gc-sections -z start-stop-gc are now zero when all SECNAME sections
been garbage collected.  This is no need for elf_x86_start_stop_gc_p.

bfd/

	* elf-bfd.h (_bfd_elf_link_iterate_on_relocs): New.
	* elf32-i386.c (elf_i386_convert_load_reloc): Don't call
	elf_x86_start_stop_gc_p.
	(elf_i386_check_relocs): Renamed to ...
	(elf_i386_scan_relocs): This.  Don't call
	_bfd_elf_make_dynamic_reloc_section.
	(elf_i386_always_size_sections): New.
	(elf_backend_check_relocs): Removed.
	(elf_backend_always_size_sections): New.
	* elf64-x86-64.c (elf_x86_64_convert_load_reloc): Don't call
	elf_x86_start_stop_gc_p.
	(elf_x86_64_check_relocs): Renamed to ...
	(elf_x86_64_scan_relocs): This.  Don't call
	_bfd_elf_make_dynamic_reloc_section.
	(elf_x86_64_always_size_sections): New.
	(elf_backend_check_relocs): Removed.
	(elf_backend_always_size_sections): New.
	* elflink.c (elf_link_check_or_scan_relocs):
	New.  Extracted from _bfd_elf_link_check_relocs.
	(_bfd_elf_link_check_relocs): Call elf_link_check_or_scan_relocs.
	* elfxx-x86.c (_bfd_x86_elf_check_relocs): New.
	* elfxx-x86.h (X86_64_NEED_DYNAMIC_RELOC_TYPE_P): New.
	(I386_NEED_DYNAMIC_RELOC_TYPE_P): Likewise.
	(X86_NEED_DYNAMIC_RELOC_TYPE_P): Likewise.
	(_bfd_x86_elf_check_relocs): Likewise.
	(elf_backend_check_relocs): Likewise.
	(elf_backend_always_size_sections): Removed.
	(elf_x86_start_stop_gc_p): Likewise.

ld/

	* testsuite/ld-i386/pr27491-1a.d: Updated.
	* testsuite/ld-x86-64/pr27491-1a.d: Likewise.
---
 bfd/elf-bfd.h                       |  4 ++
 bfd/elf32-i386.c                    | 58 ++++++++++----------
 bfd/elf64-x86-64.c                  | 55 +++++++++----------
 bfd/elflink.c                       | 23 ++++++--
 bfd/elfxx-x86.c                     | 85 +++++++++++++++++++++++++++++
 bfd/elfxx-x86.h                     | 60 +++++++++-----------
 ld/testsuite/ld-i386/pr27491-1a.d   |  4 +-
 ld/testsuite/ld-x86-64/pr27491-1a.d |  4 +-
 8 files changed, 191 insertions(+), 102 deletions(-)

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 896aa08fd76..81f8fd47db7 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2632,6 +2632,10 @@ extern int bfd_elf_add_dt_needed_tag
   (bfd *, struct bfd_link_info *);
 extern bool _bfd_elf_link_check_relocs
   (bfd *, struct bfd_link_info *);
+extern bool _bfd_elf_link_iterate_on_relocs
+ (bfd *, struct bfd_link_info *,
+  bool (*) (bfd *, struct bfd_link_info *, asection *,
+	    const Elf_Internal_Rela *));
 
 extern bool bfd_elf_link_record_dynamic_symbol
   (struct bfd_link_info *, struct elf_link_hash_entry *);
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 97962072ff0..d1f61be5044 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -522,7 +522,7 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
    Functions named elf_i386_* are called by external routines, other
    functions are only called locally.  elf_i386_* functions appear
    in this file more or less in the order in which they are called
-   from external routines.  eg. elf_i386_check_relocs is called
+   from external routines.  eg. elf_i386_scan_relocs is called
    early in the link process, elf_i386_finish_dynamic_sections is
    one of the last functions.  */
 
@@ -1106,7 +1106,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
 	    }
 
 	  /* We checked the transition before when we were called from
-	     elf_i386_check_relocs.  We only want to check the new
+	     elf_i386_scan_relocs.  We only want to check the new
 	     transition which hasn't been checked before.  */
 	  check = new_to_type != to_type && from_type == to_type;
 	  to_type = new_to_type;
@@ -1387,11 +1387,6 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
 	       || h->root.type == bfd_link_hash_defweak)
 	      && local_ref))
 	{
-	  /* Skip __start_SECNAME/__stop_SECNAME when --gc-sections
-	     -z start-stop-gc are used.  */
-	  if (elf_x86_start_stop_gc_p (link_info, h))
-	    return true;
-
 	convert_load:
 	  if (opcode == 0x8b)
 	    {
@@ -1452,21 +1447,20 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
 }
 
 /* Look through the relocs for a section during the first phase, and
-   calculate needed space in the global offset table, procedure linkage
-   table, and dynamic reloc sections.  */
+   calculate needed space in the global offset table, and procedure
+   linkage table.  */
 
 static bool
-elf_i386_check_relocs (bfd *abfd,
-		       struct bfd_link_info *info,
-		       asection *sec,
-		       const Elf_Internal_Rela *relocs)
+elf_i386_scan_relocs (bfd *abfd,
+		      struct bfd_link_info *info,
+		      asection *sec,
+		      const Elf_Internal_Rela *relocs)
 {
   struct elf_x86_link_hash_table *htab;
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
-  asection *sreloc;
   bfd_byte *contents;
   bool converted;
 
@@ -1496,8 +1490,6 @@ elf_i386_check_relocs (bfd *abfd,
 
   converted = false;
 
-  sreloc = NULL;
-
   rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; rel++)
     {
@@ -1818,18 +1810,6 @@ elf_i386_check_relocs (bfd *abfd,
 	      struct elf_dyn_relocs *p;
 	      struct elf_dyn_relocs **head;
 
-	      /* We must copy these reloc types into the output file.
-		 Create a reloc section in dynobj and make room for
-		 this reloc.  */
-	      if (sreloc == NULL)
-		{
-		  sreloc = _bfd_elf_make_dynamic_reloc_section
-		    (sec, htab->elf.dynobj, 2, abfd, /*rela?*/ false);
-
-		  if (sreloc == NULL)
-		    goto error_return;
-		}
-
 	      /* If this is a global symbol, we count the number of
 		 relocations we need for this symbol.  */
 	      if (h != NULL)
@@ -1924,6 +1904,24 @@ elf_i386_check_relocs (bfd *abfd,
   return false;
 }
 
+static bool
+elf_i386_always_size_sections (bfd *output_bfd,
+			       struct bfd_link_info *info)
+{
+  bfd *abfd;
+
+  /* Scan relocations after rel_from_abs has been set on __ehdr_start.  */
+  for (abfd = info->input_bfds;
+       abfd != (bfd *) NULL;
+       abfd = abfd->link.next)
+    if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+	&& !_bfd_elf_link_iterate_on_relocs (abfd, info,
+					     elf_i386_scan_relocs))
+      return false;
+
+  return _bfd_x86_elf_always_size_sections (output_bfd, info);
+}
+
 /* Set the correct type for an x86 ELF section.  We do this by the
    section name, which is a hack, but ought to work.  */
 
@@ -2000,7 +1998,7 @@ elf_i386_relocate_section (bfd *output_bfd,
   bool is_vxworks_tls;
   unsigned plt_entry_size;
 
-  /* Skip if check_relocs failed.  */
+  /* Skip if check_relocs or scan_relocs failed.  */
   if (input_section->check_relocs_failed)
     return false;
 
@@ -4390,7 +4388,7 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
 #define bfd_elf32_get_synthetic_symtab	      elf_i386_get_synthetic_symtab
 
 #define elf_backend_relocs_compatible	      _bfd_elf_relocs_compatible
-#define elf_backend_check_relocs	      elf_i386_check_relocs
+#define elf_backend_always_size_sections      elf_i386_always_size_sections
 #define elf_backend_create_dynamic_sections   _bfd_elf_create_dynamic_sections
 #define elf_backend_fake_sections	      elf_i386_fake_sections
 #define elf_backend_finish_dynamic_sections   elf_i386_finish_dynamic_sections
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 22aa3ee3b68..ad885f89e11 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1309,7 +1309,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
 	    }
 
 	  /* We checked the transition before when we were called from
-	     elf_x86_64_check_relocs.  We only want to check the new
+	     elf_x86_64_scan_relocs.  We only want to check the new
 	     transition which hasn't been checked before.  */
 	  check = new_to_type != to_type && from_type == to_type;
 	  to_type = new_to_type;
@@ -1628,11 +1628,6 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
 			   || h->root.type == bfd_link_hash_defweak)
 			  && h->root.u.def.section == bfd_und_section_ptr))))
 	    {
-	      /* Skip __start_SECNAME/__stop_SECNAME when --gc-sections
-	         -z start-stop-gc are used.  */
-	      if (elf_x86_start_stop_gc_p (link_info, h))
-		return true;
-
 	      /* Skip since R_X86_64_32/R_X86_64_32S may overflow.  */
 	      if (no_overflow)
 		return true;
@@ -1823,20 +1818,19 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
 }
 
 /* Look through the relocs for a section during the first phase, and
-   calculate needed space in the global offset table, procedure
-   linkage table, and dynamic reloc sections.  */
+   calculate needed space in the global offset table, and procedure
+   linkage table.  */
 
 static bool
-elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
-			 asection *sec,
-			 const Elf_Internal_Rela *relocs)
+elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
+			asection *sec,
+			const Elf_Internal_Rela *relocs)
 {
   struct elf_x86_link_hash_table *htab;
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
-  asection *sreloc;
   bfd_byte *contents;
   bool converted;
 
@@ -1866,8 +1860,6 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
   converted = false;
 
-  sreloc = NULL;
-
   rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; rel++)
     {
@@ -2263,19 +2255,6 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	      struct elf_dyn_relocs *p;
 	      struct elf_dyn_relocs **head;
 
-	      /* We must copy these reloc types into the output file.
-		 Create a reloc section in dynobj and make room for
-		 this reloc.  */
-	      if (sreloc == NULL)
-		{
-		  sreloc = _bfd_elf_make_dynamic_reloc_section
-		    (sec, htab->elf.dynobj, ABI_64_P (abfd) ? 3 : 2,
-		     abfd, /*rela?*/ true);
-
-		  if (sreloc == NULL)
-		    goto error_return;
-		}
-
 	      /* If this is a global symbol, we count the number of
 		 relocations we need for this symbol.  */
 	      if (h != NULL)
@@ -2371,6 +2350,24 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
   return false;
 }
 
+static bool
+elf_x86_64_always_size_sections (bfd *output_bfd,
+				 struct bfd_link_info *info)
+{
+  bfd *abfd;
+
+  /* Scan relocations after rel_from_abs has been set on __ehdr_start.  */
+  for (abfd = info->input_bfds;
+       abfd != (bfd *) NULL;
+       abfd = abfd->link.next)
+    if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+	&& !_bfd_elf_link_iterate_on_relocs (abfd, info,
+					     elf_x86_64_scan_relocs))
+      return false;
+
+  return _bfd_x86_elf_always_size_sections (output_bfd, info);
+}
+
 /* Return the relocation value for @tpoff relocation
    if STT_TLS virtual address is ADDRESS.  */
 
@@ -2413,7 +2410,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
   unsigned int plt_entry_size;
   bool status;
 
-  /* Skip if check_relocs failed.  */
+  /* Skip if check_relocs or scan_relocs failed.  */
   if (input_section->check_relocs_failed)
     return false;
 
@@ -5238,7 +5235,7 @@ elf_x86_64_special_sections[]=
   elf_x86_64_reloc_name_lookup
 
 #define elf_backend_relocs_compatible	    elf_x86_64_relocs_compatible
-#define elf_backend_check_relocs	    elf_x86_64_check_relocs
+#define elf_backend_always_size_sections    elf_x86_64_always_size_sections
 #define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
 #define elf_backend_finish_dynamic_sections elf_x86_64_finish_dynamic_sections
 #define elf_backend_finish_dynamic_symbol   elf_x86_64_finish_dynamic_symbol
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 08c161713cc..059461b5725 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -4008,10 +4008,13 @@ _bfd_elf_notice_as_needed (bfd *ibfd,
   return (*info->callbacks->notice) (info, NULL, NULL, ibfd, NULL, act, 0);
 }
 
-/* Check relocations an ELF object file.  */
+/* Call ACTION on each relocation in an ELF object file.  */
 
 bool
-_bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
+_bfd_elf_link_iterate_on_relocs
+  (bfd *abfd, struct bfd_link_info *info,
+   bool (*action) (bfd *, struct bfd_link_info *, asection *,
+		   const Elf_Internal_Rela *))
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   struct elf_link_hash_table *htab = elf_hash_table (info);
@@ -4035,7 +4038,6 @@ _bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
      different format.  It probably can't be done.  */
   if ((abfd->flags & DYNAMIC) == 0
       && is_elf_hash_table (&htab->root)
-      && bed->check_relocs != NULL
       && elf_object_id (abfd) == elf_hash_table_id (htab)
       && (*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
     {
@@ -4070,7 +4072,7 @@ _bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
 	  if (internal_relocs == NULL)
 	    return false;
 
-	  ok = (*bed->check_relocs) (abfd, info, o, internal_relocs);
+	  ok = action (abfd, info, o, internal_relocs);
 
 	  if (elf_section_data (o)->relocs != internal_relocs)
 	    free (internal_relocs);
@@ -4083,6 +4085,19 @@ _bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
   return true;
 }
 
+/* Check relocations in an ELF object file.  This is called after
+   all input files have been opened.  */
+
+bool
+_bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
+{
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  if (bed->check_relocs != NULL)
+    return _bfd_elf_link_iterate_on_relocs (abfd, info,
+					    bed->check_relocs);
+  return true;
+}
+
 /* Add symbols from an ELF object file to the linker hash table.  */
 
 static bool
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index ca4b90e22cc..25f7717ea88 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -892,6 +892,91 @@ _bfd_x86_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
   return _bfd_elf_link_check_relocs (abfd, info);
 }
 
+/* Look through the relocs for a section before allocation to make the
+   dynamic reloc section.  */
+
+bool
+_bfd_x86_elf_check_relocs (bfd *abfd,
+			   struct bfd_link_info *info,
+			   asection *sec,
+			   const Elf_Internal_Rela *relocs)
+{
+  struct elf_x86_link_hash_table *htab;
+  Elf_Internal_Shdr *symtab_hdr;
+  struct elf_link_hash_entry **sym_hashes;
+  const Elf_Internal_Rela *rel;
+  const Elf_Internal_Rela *rel_end;
+  asection *sreloc;
+  const struct elf_backend_data *bed;
+  bool is_x86_64;
+
+  if (bfd_link_relocatable (info))
+    return true;
+
+  bed = get_elf_backend_data (abfd);
+  htab = elf_x86_hash_table (info, bed->target_id);
+  if (htab == NULL)
+    {
+      sec->check_relocs_failed = 1;
+      return false;
+    }
+
+  is_x86_64 = bed->target_id == X86_64_ELF_DATA;
+
+  symtab_hdr = &elf_symtab_hdr (abfd);
+  sym_hashes = elf_sym_hashes (abfd);
+
+  rel_end = relocs + sec->reloc_count;
+  for (rel = relocs; rel < rel_end; rel++)
+    {
+      unsigned int r_type;
+      unsigned int r_symndx;
+      struct elf_link_hash_entry *h;
+
+      r_symndx = htab->r_sym (rel->r_info);
+      r_type = ELF32_R_TYPE (rel->r_info);
+
+      if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
+	{
+	  /* xgettext:c-format */
+	  _bfd_error_handler (_("%pB: bad symbol index: %d"),
+			      abfd, r_symndx);
+	  goto error_return;
+	}
+
+      if (r_symndx < symtab_hdr->sh_info)
+	h = NULL;
+      else
+	{
+	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+	  while (h->root.type == bfd_link_hash_indirect
+		 || h->root.type == bfd_link_hash_warning)
+	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+	}
+
+      if (X86_NEED_DYNAMIC_RELOC_TYPE_P (is_x86_64, r_type)
+	  && NEED_DYNAMIC_RELOCATION_P (is_x86_64, info, true, h, sec,
+					r_type, htab->pointer_r_type))
+	{
+	  /* We may copy these reloc types into the output file.
+	     Create a reloc section in dynobj and make room for
+	     this reloc.  */
+	  sreloc = _bfd_elf_make_dynamic_reloc_section
+	    (sec, htab->elf.dynobj, ABI_64_P (abfd) ? 3 : 2,
+	     abfd, sec->use_rela_p);
+
+	  if (sreloc != NULL)
+	    return true;
+
+  error_return:
+	  sec->check_relocs_failed = 1;
+	  return false;
+	}
+    }
+
+  return true;
+}
+
 bool
 _bfd_elf_x86_valid_reloc_p (asection *input_section,
 			    struct bfd_link_info *info,
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index 16565a5638b..1bb80280918 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -47,6 +47,25 @@
 #define X86_SIZE_TYPE_P(IS_X86_64, TYPE) \
   ((IS_X86_64) ? X86_64_SIZE_TYPE_P(TYPE) : I386_SIZE_TYPE_P (TYPE))
 
+#define X86_64_NEED_DYNAMIC_RELOC_TYPE_P(TYPE) \
+  (X86_64_SIZE_TYPE_P (TYPE) \
+   || X86_64_PCREL_TYPE_P (TYPE) \
+   || (TYPE) == R_X86_64_8 \
+   || (TYPE) == R_X86_64_16 \
+   || (TYPE) == R_X86_64_32 \
+   || (TYPE) == R_X86_64_32S \
+   || (TYPE) == R_X86_64_64)
+#define I386_NEED_DYNAMIC_RELOC_TYPE_P(TYPE) \
+  (I386_SIZE_TYPE_P (TYPE) \
+   || I386_PCREL_TYPE_P (TYPE) \
+   || (TYPE) == R_386_32 \
+   || (TYPE) == R_386_TLS_LE \
+   || (TYPE) == R_386_TLS_LE_32)
+#define X86_NEED_DYNAMIC_RELOC_TYPE_P(IS_X86_64, TYPE) \
+  ((IS_X86_64) \
+   ? X86_64_NEED_DYNAMIC_RELOC_TYPE_P (TYPE) \
+   : I386_NEED_DYNAMIC_RELOC_TYPE_P (TYPE))
+
 #define PLT_CIE_LENGTH		20
 #define PLT_FDE_LENGTH		36
 #define PLT_FDE_START_OFFSET	4 + PLT_CIE_LENGTH + 8
@@ -653,6 +672,10 @@ extern int _bfd_x86_elf_compare_relocs
 extern bool _bfd_x86_elf_link_check_relocs
   (bfd *, struct bfd_link_info *);
 
+extern bool _bfd_x86_elf_check_relocs
+  (bfd *, struct bfd_link_info *, asection *,
+   const Elf_Internal_Rela *);
+
 extern bool _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 *,
@@ -730,10 +753,10 @@ extern void _bfd_x86_elf_link_report_relative_reloc
 #define bfd_elf32_bfd_link_check_relocs \
   _bfd_x86_elf_link_check_relocs
 
+#define elf_backend_check_relocs \
+  _bfd_x86_elf_check_relocs
 #define elf_backend_size_dynamic_sections \
   _bfd_x86_elf_size_dynamic_sections
-#define elf_backend_always_size_sections \
-  _bfd_x86_elf_always_size_sections
 #define elf_backend_merge_symbol_attribute \
   _bfd_x86_elf_merge_symbol_attribute
 #define elf_backend_copy_indirect_symbol \
@@ -757,39 +780,6 @@ extern void _bfd_x86_elf_link_report_relative_reloc
 
 #define ELF_P_ALIGN ELF_MINPAGESIZE
 
-/* Return true if H is a __start_SECNAME/__stop_SECNAME symbol for the
-   SECNAME section which has been garbage collected by --gc-sections
-   -z start-stop-gc.  */
-
-static inline bool
-elf_x86_start_stop_gc_p (struct bfd_link_info *link_info,
-			 struct elf_link_hash_entry *h)
-{
-  if (h->start_stop
-      && link_info->gc_sections
-      && link_info->start_stop_gc)
-    {
-      asection *s = h->root.u.def.section;
-
-      do
-	{
-	  /* Return false if any SECNAME section is kept.  */
-	  if (s->gc_mark)
-	    return false;
-	  s = bfd_get_next_section_by_name (s->owner, s);
-	}
-      while (s != NULL);
-
-      /* Return true only if all SECNAME sections have been garbage
-	 collected.  */
-      return true;
-    }
-
-  /* Return false if H isn't a __start_SECNAME/__stop_SECNAME symbol or
-     --gc-sections or -z start-stop-gc isn't used.  */
-  return false;
-}
-
 /* Allocate x86 GOT info for local symbols.  */
 
 static inline bool
diff --git a/ld/testsuite/ld-i386/pr27491-1a.d b/ld/testsuite/ld-i386/pr27491-1a.d
index 006c17695c1..39b25f6507f 100644
--- a/ld/testsuite/ld-i386/pr27491-1a.d
+++ b/ld/testsuite/ld-i386/pr27491-1a.d
@@ -9,6 +9,6 @@
 Disassembly of section .text:
 
 [a-f0-9]+ <foo>:
- +[a-f0-9]+:	8b 83 ([0-9a-f]{2} ){4}[ \t]+mov +-0x[a-f0-9]+\(%ebx\),%eax
- +[a-f0-9]+:	8b 83 ([0-9a-f]{2} ){4}[ \t]+mov +-0x[a-f0-9]+\(%ebx\),%eax
+ +[a-f0-9]+:	c7 c0 00 00 00 00    	mov    \$0x0,%eax
+ +[a-f0-9]+:	c7 c0 00 00 00 00    	mov    \$0x0,%eax
 #pass
diff --git a/ld/testsuite/ld-x86-64/pr27491-1a.d b/ld/testsuite/ld-x86-64/pr27491-1a.d
index ade5c6fa4f9..215124c6401 100644
--- a/ld/testsuite/ld-x86-64/pr27491-1a.d
+++ b/ld/testsuite/ld-x86-64/pr27491-1a.d
@@ -9,6 +9,6 @@
 Disassembly of section .text:
 
 [a-f0-9]+ <foo>:
- +[a-f0-9]+:	48 8b 05 ([0-9a-f]{2} ){4}[ \t]+mov +0x[a-f0-9]+\(%rip\),%rax[ \t]+# [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
- +[a-f0-9]+:	48 8b 05 ([0-9a-f]{2} ){4}[ \t]+mov +0x[a-f0-9]+\(%rip\),%rax[ \t]+# [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
+ +[a-f0-9]+:	48 c7 c0 00 00 00 00 	mov    \$0x0,%rax
+ +[a-f0-9]+:	48 c7 c0 00 00 00 00 	mov    \$0x0,%rax
 #pass
-- 
2.33.1


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 02/10] elf: Add .relr.dyn to special_sections_r
  2022-01-07 19:06 [PATCH 0/10] ld: Implement DT_RELR for x86 H.J. Lu
  2022-01-07 19:06 ` [PATCH 01/10] ld: Extract _bfd_elf_link_iterate_on_relocs H.J. Lu
@ 2022-01-07 19:06 ` H.J. Lu
  2022-01-07 19:06 ` [PATCH 03/10] elf: Extract _bfd_elf_process_reverse_copy H.J. Lu
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-07 19:06 UTC (permalink / raw)
  To: binutils; +Cc: Nick Clifton, Alan Modra, libc-alpha

	* elf.c (special_sections_r): Add .relr.dyn.
---
 bfd/elf.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/bfd/elf.c b/bfd/elf.c
index 1003bd2cdbe..ef0d18105ba 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -2714,6 +2714,7 @@ static const struct bfd_elf_special_section special_sections_r[] =
 {
   { STRING_COMMA_LEN (".rodata"), -2, SHT_PROGBITS, SHF_ALLOC },
   { STRING_COMMA_LEN (".rodata1"), 0, SHT_PROGBITS, SHF_ALLOC },
+  { STRING_COMMA_LEN (".relr.dyn"), 0, SHT_RELR, SHF_ALLOC },
   { STRING_COMMA_LEN (".rela"),	  -1, SHT_RELA,	    0 },
   { STRING_COMMA_LEN (".rel"),	  -1, SHT_REL,	    0 },
   { NULL,		    0,	   0, 0,	    0 }
-- 
2.33.1


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 03/10] elf: Extract _bfd_elf_process_reverse_copy
  2022-01-07 19:06 [PATCH 0/10] ld: Implement DT_RELR for x86 H.J. Lu
  2022-01-07 19:06 ` [PATCH 01/10] ld: Extract _bfd_elf_link_iterate_on_relocs H.J. Lu
  2022-01-07 19:06 ` [PATCH 02/10] elf: Add .relr.dyn to special_sections_r H.J. Lu
@ 2022-01-07 19:06 ` H.J. Lu
  2022-01-07 19:06 ` [PATCH 04/10] elf: Pass need_layout to _bfd_elf_map_sections_to_segments H.J. Lu
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-07 19:06 UTC (permalink / raw)
  To: binutils; +Cc: Nick Clifton, Alan Modra, libc-alpha

Extract _bfd_elf_process_reverse_copy from elf_link_input_bfd so that
it can be called in check_relocs to set SEC_ELF_REVERSE_COPY before
elf_link_input_bfd is called.

	* elf-bfd.h (_bfd_elf_process_reverse_copy): New prototype.
	* elflink.c (_bfd_elf_process_reverse_copy): New.  Extracted
	from elf_link_input_bfd.
	(elf_link_input_bfd): Call _bfd_elf_process_reverse_copy.
---
 bfd/elf-bfd.h |  2 ++
 bfd/elflink.c | 60 ++++++++++++++++++++++++++++++++-------------------
 2 files changed, 40 insertions(+), 22 deletions(-)

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 81f8fd47db7..2441b3c0cd7 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2331,6 +2331,8 @@ extern const struct bfd_elf_special_section *_bfd_elf_get_special_section
   (const char *, const struct bfd_elf_special_section *, unsigned int);
 extern const struct bfd_elf_special_section *_bfd_elf_get_sec_type_attr
   (bfd *, asection *);
+extern bool _bfd_elf_process_reverse_copy (asection *, unsigned int,
+					   unsigned int);
 
 extern bool _bfd_elf_link_hide_sym_by_version
   (struct bfd_link_info *, struct elf_link_hash_entry *);
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 059461b5725..29ef9ddf8b9 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -10851,6 +10851,41 @@ _bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info)
   return kept;
 }
 
+/* Set SEC_ELF_REVERSE_COPY on section S when we need to reverse-copy
+   input .ctors/.dtors sections if they are placed in .init_array or
+   .finit_array for output.  ADDRESS_SIZE is address in bytes.
+   INT_RELS_PER_EXT_REL is the number of internal relocations to
+   allocate per external relocation entry.  */
+
+bool
+_bfd_elf_process_reverse_copy (asection *s, unsigned int address_size,
+			       unsigned int int_rels_per_ext_rel)
+{
+  if (s->size <= address_size
+      || (s->flags & SEC_ELF_REVERSE_COPY) != 0)
+    return true;
+
+  if (((startswith (s->name, ".ctors")
+	&& strcmp (s->output_section->name, ".init_array") == 0)
+       || (startswith (s->name, ".dtors")
+	   && strcmp (s->output_section->name, ".fini_array") == 0))
+      && (s->name[6] == 0 || s->name[6] == '.'))
+    {
+      if (s->size * int_rels_per_ext_rel
+	  != s->reloc_count * address_size)
+	{
+	  _bfd_error_handler
+	    /* xgettext:c-format */
+	    (_("error: %pB: size of section %pA is not multiple of "
+	       "address size"), s->owner, s);
+	  bfd_set_error (bfd_error_bad_value);
+	  return false;
+	}
+      s->flags |= SEC_ELF_REVERSE_COPY;
+    }
+  return true;
+}
+
 /* Link an input file into the linker output file.  This function
    handles all the sections and relocations of the input file at once.
    This is so that we only have to read the local symbols once, and
@@ -11249,28 +11284,9 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 
 	  /* We need to reverse-copy input .ctors/.dtors sections if
 	     they are placed in .init_array/.finit_array for output.  */
-	  if (o->size > address_size
-	      && ((startswith (o->name, ".ctors")
-		   && strcmp (o->output_section->name,
-			      ".init_array") == 0)
-		  || (startswith (o->name, ".dtors")
-		      && strcmp (o->output_section->name,
-				 ".fini_array") == 0))
-	      && (o->name[6] == 0 || o->name[6] == '.'))
-	    {
-	      if (o->size * bed->s->int_rels_per_ext_rel
-		  != o->reloc_count * address_size)
-		{
-		  _bfd_error_handler
-		    /* xgettext:c-format */
-		    (_("error: %pB: size of section %pA is not "
-		       "multiple of address size"),
-		     input_bfd, o);
-		  bfd_set_error (bfd_error_bad_value);
-		  return false;
-		}
-	      o->flags |= SEC_ELF_REVERSE_COPY;
-	    }
+	  if (!_bfd_elf_process_reverse_copy (o, address_size,
+					      bed->s->int_rels_per_ext_rel))
+	    return false;
 
 	  action_discarded = -1;
 	  if (!elf_section_ignore_discarded_relocs (o))
-- 
2.33.1


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 04/10] elf: Pass need_layout to _bfd_elf_map_sections_to_segments
  2022-01-07 19:06 [PATCH 0/10] ld: Implement DT_RELR for x86 H.J. Lu
                   ` (2 preceding siblings ...)
  2022-01-07 19:06 ` [PATCH 03/10] elf: Extract _bfd_elf_process_reverse_copy H.J. Lu
@ 2022-01-07 19:06 ` H.J. Lu
  2022-01-07 19:06 ` [PATCH 05/10] ld: Initial DT_RELR support H.J. Lu
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-07 19:06 UTC (permalink / raw)
  To: binutils; +Cc: Nick Clifton, Alan Modra, libc-alpha

On some targets, the DT_RELR section size can be computed only after all
symbols addresses can be determined.  Update ldelf_map_segments to pass
need_layout to _bfd_elf_map_sections_to_segments which will size DT_RELR
section and set need_layout to true if the DT_RELR section size is changed.

bfd/

	* elf-bfd.h (_bfd_elf_map_sections_to_segments): Add a bool
	pointer argument.
	* elf.c (_bfd_elf_map_sections_to_segments): Add a bool pointer
	argument to indicate if section layout needs update.
	(assign_file_positions_for_load_sections): Pass NULL to
	_bfd_elf_map_sections_to_segments.
	* elflink.c (_bfd_elf_strip_zero_sized_dynamic_sections): Pass
	NULL to _bfd_elf_map_sections_to_segments.

ld/

	* ldelfgen.c (ldelf_map_segments): Pass &need_layout to
	_bfd_elf_map_sections_to_segments.
---
 bfd/elf-bfd.h | 2 +-
 bfd/elf.c     | 9 ++++++---
 bfd/elflink.c | 3 ++-
 ld/ldelfgen.c | 3 ++-
 4 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 2441b3c0cd7..c4d2ef00d6b 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2718,7 +2718,7 @@ extern struct elf_segment_map * _bfd_elf_make_dynamic_segment
   (bfd *, asection *);
 
 extern bool _bfd_elf_map_sections_to_segments
-  (bfd *, struct bfd_link_info *);
+  (bfd *, struct bfd_link_info *, bool *);
 
 extern bool _bfd_elf_is_function_type (unsigned int);
 
diff --git a/bfd/elf.c b/bfd/elf.c
index ef0d18105ba..8b866b63e18 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -4609,10 +4609,13 @@ elf_modify_segment_map (bfd *abfd,
 #define IS_TBSS(s) \
   ((s->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) == SEC_THREAD_LOCAL)
 
-/* Set up a mapping from BFD sections to program segments.  */
+/* Set up a mapping from BFD sections to program segments.  Update
+   NEED_LAYOUT if the section layout is changed.  */
 
 bool
-_bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
+_bfd_elf_map_sections_to_segments (bfd *abfd,
+				   struct bfd_link_info *info,
+				   bool *need_layout ATTRIBUTE_UNUSED)
 {
   unsigned int count;
   struct elf_segment_map *m;
@@ -5416,7 +5419,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
   unsigned int opb = bfd_octets_per_byte (abfd, NULL);
 
   if (link_info == NULL
-      && !_bfd_elf_map_sections_to_segments (abfd, link_info))
+      && !_bfd_elf_map_sections_to_segments (abfd, link_info, NULL))
     return false;
 
   alloc = 0;
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 29ef9ddf8b9..bea413ec24e 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -3676,7 +3676,8 @@ _bfd_elf_strip_zero_sized_dynamic_sections (struct bfd_link_info *info)
     {
       /* Regenerate program headers.  */
       elf_seg_map (info->output_bfd) = NULL;
-      return _bfd_elf_map_sections_to_segments (info->output_bfd, info);
+      return _bfd_elf_map_sections_to_segments (info->output_bfd, info,
+						NULL);
     }
 
   return true;
diff --git a/ld/ldelfgen.c b/ld/ldelfgen.c
index 5c033bbfbe0..58b37c65bc9 100644
--- a/ld/ldelfgen.c
+++ b/ld/ldelfgen.c
@@ -304,7 +304,8 @@ ldelf_map_segments (bool need_layout)
 	  if (lang_phdr_list == NULL)
 	    elf_seg_map (link_info.output_bfd) = NULL;
 	  if (!_bfd_elf_map_sections_to_segments (link_info.output_bfd,
-						  &link_info))
+						  &link_info,
+						  &need_layout))
 	    einfo (_("%F%P: map sections to segments failed: %E\n"));
 
 	  if (phdr_size != elf_program_header_size (link_info.output_bfd))
-- 
2.33.1


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 05/10] ld: Initial DT_RELR support
  2022-01-07 19:06 [PATCH 0/10] ld: Implement DT_RELR for x86 H.J. Lu
                   ` (3 preceding siblings ...)
  2022-01-07 19:06 ` [PATCH 04/10] elf: Pass need_layout to _bfd_elf_map_sections_to_segments H.J. Lu
@ 2022-01-07 19:06 ` H.J. Lu
  2022-01-08  2:10   ` Fangrui Song
  2022-01-08  8:30   ` Fangrui Song
  2022-01-07 19:06 ` [PATCH 06/10] elf: Add size_relative_relocs and finish_relative_relocs H.J. Lu
                   ` (5 subsequent siblings)
  10 siblings, 2 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-07 19:06 UTC (permalink / raw)
  To: binutils; +Cc: Nick Clifton, Alan Modra, libc-alpha

Add a -z pack-relative-relocs option to enable DT_RELR and create a
relr.dyn section for DT_RELR.

-z pack-relative-relocs implies -z combreloc and --relax.  --no-relax
and -z nocombreloc imply -z nopack-relative-relocs.

-z pack-relative-relocs is chosen over the similar option in lld,
--pack-dyn-relocs=relr, to implement a glibc binary lockout mechanism
with a special glibc version symbol, to avoid random crashes of DT_RELR
binaries with the existing glibc binaries.

bfd/

	* elf-bfd.h (elf_link_hash_table): Add srelrdyn.
	* elflink.c (_bfd_elf_link_create_dynamic_sections): Create a
	.relr.dyn section for DT_RELR.

include/

	* bfdlink.h (bfd_link_info): Add enable_dt_relr.

ld/

	* News: Mention -z pack-relative-relocs and
	-z nopack-relative-relocs.
	* ld.texi: Document -z pack-relative-relocs and
	-z nopack-relative-relocs.
	* ldelf.c (ldelf_after_parse): Disable DT_RELR if not building
	PIE nor shared library.  Add 3 spare dynamic tags for DT_RELR,
	DT_RELRSZ and DT_RELRENT.
	* lexsup.c (parse_args): Disable DT_RELR for --no-relax.
	* emulparams/elf32_x86_64.sh: Source dt-relr.sh.
	* emulparams/elf_i386.sh: Likewise.
	* emulparams/elf_x86_64.sh: Likewise.
	* emulparams/dt-relr.sh: New file.
	* emultempl/elf.em (gld${EMULATION_NAME}_handle_option): Disable
	DT_RELR for -z nocombreloc.
	* scripttempl/elf.sc: Support .relr.dyn.
---
 bfd/elf-bfd.h                 |  1 +
 bfd/elflink.c                 | 11 +++++++++++
 include/bfdlink.h             |  4 ++++
 ld/NEWS                       |  3 +++
 ld/emulparams/dt-relr.sh      | 21 +++++++++++++++++++++
 ld/emulparams/elf32_x86_64.sh |  1 +
 ld/emulparams/elf_i386.sh     |  1 +
 ld/emulparams/elf_x86_64.sh   |  1 +
 ld/emultempl/elf.em           |  5 ++++-
 ld/ld.texi                    | 14 +++++++++++++-
 ld/ldelf.c                    | 13 +++++++++++++
 ld/lexsup.c                   |  1 +
 ld/scripttempl/elf.sc         |  4 ++++
 13 files changed, 78 insertions(+), 2 deletions(-)
 create mode 100644 ld/emulparams/dt-relr.sh

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index c4d2ef00d6b..4e73d79ee77 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -707,6 +707,7 @@ struct elf_link_hash_table
   asection *irelplt;
   asection *irelifunc;
   asection *dynsym;
+  asection *srelrdyn;
 };
 
 /* Returns TRUE if the hash table is a struct elf_link_hash_table.  */
diff --git a/bfd/elflink.c b/bfd/elflink.c
index bea413ec24e..d51b00b6c10 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -359,6 +359,17 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 	elf_section_data (s)->this_hdr.sh_entsize = 4;
     }
 
+  if (info->enable_dt_relr)
+    {
+      s = bfd_make_section_anyway_with_flags (abfd, ".relr.dyn",
+					      (bed->dynamic_sec_flags
+					       | SEC_READONLY));
+      if (s == NULL
+	  || !bfd_set_section_alignment (s, bed->s->log_file_align))
+	return false;
+      elf_hash_table (info)->srelrdyn = s;
+    }
+
   /* Let the backend create the rest of the sections.  This lets the
      backend set the right flags.  The backend will normally create
      the .got and .plt sections.  */
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 01f57c22edf..92e3e32360b 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -413,6 +413,10 @@ struct bfd_link_info
   /* TRUE if PT_GNU_RELRO segment should be created.  */
   unsigned int relro: 1;
 
+  /* TRUE if DT_RELR should be enabled for compact relative
+     relocations.  */
+  unsigned int enable_dt_relr: 1;
+
   /* TRUE if separate code segment should be created.  */
   unsigned int separate_code: 1;
 
diff --git a/ld/NEWS b/ld/NEWS
index 5d3d80dbbba..77c716b577d 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Add -z pack-relative-relocs/-z no pack-relative-relocs to x86 ELF
+  linker to pack relative relocations in the DT_RELR section.
+
 * Add support for the LoongArch architecture.
 
 * Add -z indirect-extern-access/-z noindirect-extern-access to x86 ELF
diff --git a/ld/emulparams/dt-relr.sh b/ld/emulparams/dt-relr.sh
new file mode 100644
index 00000000000..ed93ee2b5c2
--- /dev/null
+++ b/ld/emulparams/dt-relr.sh
@@ -0,0 +1,21 @@
+HAVE_DT_RELR=yes
+PARSE_AND_LIST_OPTIONS_PACK_RELATIVE_RELOCS='
+  fprintf (file, _("\
+  -z pack-relative-relocs     Pack relative relocations\n"));
+  fprintf (file, _("\
+  -z nopack-relative-relocs   Do not pack relative relocations (default)\n"));
+'
+
+PARSE_AND_LIST_ARGS_CASE_Z_PACK_RELATIVE_RELOCS='
+      else if (strcmp (optarg, "pack-relative-relocs") == 0)
+	{
+	  link_info.enable_dt_relr = true;
+	  link_info.combreloc = true;
+	}
+      else if (strcmp (optarg, "nopack-relative-relocs") == 0)
+	link_info.enable_dt_relr = false;
+'
+
+
+PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_PACK_RELATIVE_RELOCS"
+PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_PACK_RELATIVE_RELOCS"
diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh
index ac0a7aa6dcf..4bff41287c1 100644
--- a/ld/emulparams/elf32_x86_64.sh
+++ b/ld/emulparams/elf32_x86_64.sh
@@ -7,6 +7,7 @@ source_sh ${srcdir}/emulparams/cet.sh
 source_sh ${srcdir}/emulparams/x86-report-relative.sh
 source_sh ${srcdir}/emulparams/x86-64-level.sh
 source_sh ${srcdir}/emulparams/static.sh
+source_sh ${srcdir}/emulparams/dt-relr.sh
 SCRIPT_NAME=elf
 ELFSIZE=32
 OUTPUT_FORMAT="elf32-x86-64"
diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh
index 98532e5edbc..ae17bb4b3f7 100644
--- a/ld/emulparams/elf_i386.sh
+++ b/ld/emulparams/elf_i386.sh
@@ -6,6 +6,7 @@ source_sh ${srcdir}/emulparams/cet.sh
 source_sh ${srcdir}/emulparams/x86-report-relative.sh
 source_sh ${srcdir}/emulparams/x86-64-level.sh
 source_sh ${srcdir}/emulparams/static.sh
+source_sh ${srcdir}/emulparams/dt-relr.sh
 SCRIPT_NAME=elf
 OUTPUT_FORMAT="elf32-i386"
 NO_RELA_RELOCS=yes
diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh
index 48d0974711b..5f2743ed409 100644
--- a/ld/emulparams/elf_x86_64.sh
+++ b/ld/emulparams/elf_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-lam.sh
 source_sh ${srcdir}/emulparams/static.sh
+source_sh ${srcdir}/emulparams/dt-relr.sh
 SCRIPT_NAME=elf
 ELFSIZE=64
 OUTPUT_FORMAT="elf64-x86-64"
diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em
index 59775260b06..7a32a4cc4d4 100644
--- a/ld/emultempl/elf.em
+++ b/ld/emultempl/elf.em
@@ -822,7 +822,10 @@ fragment <<EOF
       else if (strcmp (optarg, "combreloc") == 0)
 	link_info.combreloc = true;
       else if (strcmp (optarg, "nocombreloc") == 0)
-	link_info.combreloc = false;
+	{
+	  link_info.combreloc = false;
+	  link_info.enable_dt_relr = false;
+	}
       else if (strcmp (optarg, "nocopyreloc") == 0)
 	link_info.nocopyreloc = true;
 EOF
diff --git a/ld/ld.texi b/ld/ld.texi
index edcf1772855..457089ec06a 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -1242,6 +1242,7 @@ Supported for Linux/i386 and Linux/x86_64.
 @itemx nocombreloc
 Combine multiple dynamic relocation sections and sort to improve
 dynamic symbol lookup caching.  Do not do this if @samp{nocombreloc}.
+@samp{nocombreloc} implies @samp{nopack-relative-relocs}.
 
 @item common
 @itemx nocommon
@@ -1430,6 +1431,16 @@ called.
 @item origin
 Specify that the object requires @samp{$ORIGIN} handling in paths.
 
+@item pack-relative-relocs
+@itemx nopack-relative-relocs
+Generate compact relative relocation in position-independent executable
+and shared library.  It adds @code{DT_RELR}, @code{DT_RELRSZ} and
+@code{DT_RELRENT} entries to the dynamic section.  It is ignored when
+building position-dependent executable and relocatable output.  This
+option also implies @option{combreloc} and @option{--relax}.
+@option{nopack-relative-relocs} is the default, which disables
+compact relative relocation.  Supported for i386 and x86-64.
+
 @item relro
 @itemx norelro
 Create an ELF @code{PT_GNU_RELRO} segment header in the object.  This
@@ -2215,7 +2226,8 @@ family of processors.
 @end ifset
 
 On platforms where the feature is supported, the option
-@option{--no-relax} will disable it.
+@option{--no-relax} will disable it and also imply
+@option{-z nopack-relative-relocs}.
 
 On platforms where the feature is not supported, both @option{--relax}
 and @option{--no-relax} are accepted, but ignored.
diff --git a/ld/ldelf.c b/ld/ldelf.c
index d15f027e91a..1978ac477f5 100644
--- a/ld/ldelf.c
+++ b/ld/ldelf.c
@@ -71,6 +71,19 @@ ldelf_after_parse (void)
 	einfo (_("%P: warning: -z dynamic-undefined-weak ignored\n"));
       link_info.dynamic_undefined_weak = 0;
     }
+
+  /* Disable DT_RELR if not building PIE nor shared library.  */
+  if (!bfd_link_pic (&link_info))
+    link_info.enable_dt_relr = 0;
+
+  if (link_info.enable_dt_relr)
+    {
+      ENABLE_RELAXATION;
+
+      /* Add 3 spare tags for DT_RELR, DT_RELRSZ and DT_RELRENT.  */
+      link_info.spare_dynamic_tags += 3;
+    }
+
   after_parse_default ();
   if (link_info.commonpagesize > link_info.maxpagesize)
     einfo (_("%F%P: common page size (0x%v) > maximum page size (0x%v)\n"),
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 5acc47ed5a0..3942716963a 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -1229,6 +1229,7 @@ parse_args (unsigned argc, char **argv)
 	  break;
 	case OPTION_NO_RELAX:
 	  DISABLE_RELAXATION;
+	  link_info.enable_dt_relr = false;
 	  break;
 	case OPTION_RELAX:
 	  ENABLE_RELAXATION;
diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
index a9a39ad402c..f3552a4a554 100644
--- a/ld/scripttempl/elf.sc
+++ b/ld/scripttempl/elf.sc
@@ -10,6 +10,7 @@
 #		empty.
 #	HAVE_NOINIT - Include a .noinit output section in the script.
 #	HAVE_PERSISTENT - Include a .persistent output section in the script.
+#	HAVE_DT_RELR - Include a .relr.dyn output section in the script.
 #	SMALL_DATA_CTOR - .ctors contains small data.
 #	SMALL_DATA_DTOR - .dtors contains small data.
 #	DATA_ADDR - if end-of-text-plus-one-page isn't right for data start
@@ -520,6 +521,9 @@ emit_dyn()
     fi
   fi
   rm -f ldscripts/dyntmp.$$
+  if test -n "${COMBRELOC}" && test -n "${HAVE_DT_RELR}"; then
+    echo "  .relr.dyn : { *(.relr.dyn) }"
+  fi
 }
 
 test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn
-- 
2.33.1


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 06/10] elf: Add size_relative_relocs and finish_relative_relocs
  2022-01-07 19:06 [PATCH 0/10] ld: Implement DT_RELR for x86 H.J. Lu
                   ` (4 preceding siblings ...)
  2022-01-07 19:06 ` [PATCH 05/10] ld: Initial DT_RELR support H.J. Lu
@ 2022-01-07 19:06 ` H.J. Lu
  2022-01-07 19:06 ` [PATCH 07/10] elf: Support DT_RELR in linker tests H.J. Lu
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-07 19:06 UTC (permalink / raw)
  To: binutils; +Cc: Nick Clifton, Alan Modra, libc-alpha

On some targets, the DT_RELR section size can be computed only after all
symbols addresses can be determined.  Set the preliminary DT_RELR section
size before mapping sections to segments and set the final DT_RELR section
size after regular symbol processing is done.

	* elf-bfd.h (elf_backend_data): Add size_relative_relocs and
	finish_relative_relocs.
	* elf.c (_bfd_elf_map_sections_to_segments): Call
	size_relative_relocs if DT_RELR is enabled.
	* elflink.c (bfd_elf_final_link): Call finish_relative_relocs
	after regular symbol processing is finished if DT_RELR is enabled.
	* elfxx-target.h (elf_backend_size_relative_relocs): New.
	(elf_backend_finish_relative_relocs): Likewise.
	(elfNN_bed): Add elf_backend_size_relative_relocs and
	elf_backend_finish_relative_relocs.
---
 bfd/elf-bfd.h      | 10 ++++++++++
 bfd/elf.c          | 14 ++++++++++++--
 bfd/elflink.c      |  8 ++++++++
 bfd/elfxx-target.h |  8 ++++++++
 4 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 4e73d79ee77..c006008ab7e 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1105,6 +1105,16 @@ struct elf_backend_data
     (bfd *abfd, struct bfd_link_info *info, asection *o,
      const Elf_Internal_Rela *relocs);
 
+  /* The SIZE_RELATIVE_RELOCS function is called to size relative
+     relocations when mappig sections to segments.  */
+  bool (*size_relative_relocs)
+    (struct bfd_link_info *info, bool *need_layout);
+
+  /* The FINISH_RELATIVE_RELOCS function is called to finish relative
+     relocations in bfd_elf_final_link.  */
+  bool (*finish_relative_relocs)
+    (struct bfd_link_info *info);
+
   /* The CHECK_DIRECTIVES function is called once per input file by
      the add_symbols phase of the ELF backend linker.  The function
      must inspect the bfd and create any additional symbols according
diff --git a/bfd/elf.c b/bfd/elf.c
index 8b866b63e18..14c2c7ba734 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -4615,7 +4615,7 @@ elf_modify_segment_map (bfd *abfd,
 bool
 _bfd_elf_map_sections_to_segments (bfd *abfd,
 				   struct bfd_link_info *info,
-				   bool *need_layout ATTRIBUTE_UNUSED)
+				   bool *need_layout)
 {
   unsigned int count;
   struct elf_segment_map *m;
@@ -4626,7 +4626,17 @@ _bfd_elf_map_sections_to_segments (bfd *abfd,
   no_user_phdrs = elf_seg_map (abfd) == NULL;
 
   if (info != NULL)
-    info->user_phdrs = !no_user_phdrs;
+    {
+      info->user_phdrs = !no_user_phdrs;
+
+      /* Size the relative relocations if DT_RELR is enabled.  */
+      if (info->enable_dt_relr
+	  && need_layout != NULL
+	  && bed->size_relative_relocs
+	  && !bed->size_relative_relocs (info, need_layout))
+	info->callbacks->einfo
+	  (_("%F%P: failed to size relative relocations\n"));
+    }
 
   if (no_user_phdrs && bfd_count_sections (abfd) != 0)
     {
diff --git a/bfd/elflink.c b/bfd/elflink.c
index d51b00b6c10..31b13f5df7a 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -12625,6 +12625,14 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   if (!_bfd_elf_fixup_eh_frame_hdr (info))
     return false;
 
+  /* Finish relative relocations here after regular symbol processing
+     is finished if DT_RELR is enabled.  */
+  if (info->enable_dt_relr
+      && bed->finish_relative_relocs
+      && !bed->finish_relative_relocs (info))
+    info->callbacks->einfo
+      (_("%F%P: %pB: failed to finish relative relocations\n"), abfd);
+
   /* Since ELF permits relocations to be against local symbols, we
      must have the local symbols available when we do the relocations.
      Since we would rather only read the local symbols once, and we
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 360b056ff58..e31985ef777 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -478,6 +478,12 @@
 #ifndef elf_backend_check_relocs
 #define elf_backend_check_relocs	0
 #endif
+#ifndef elf_backend_size_relative_relocs
+#define elf_backend_size_relative_relocs 0
+#endif
+#ifndef elf_backend_finish_relative_relocs
+#define elf_backend_finish_relative_relocs 0
+#endif
 #ifndef elf_backend_check_directives
 #define elf_backend_check_directives	0
 #endif
@@ -842,6 +848,8 @@ static const struct elf_backend_data elfNN_bed =
   elf_backend_omit_section_dynsym,
   elf_backend_relocs_compatible,
   elf_backend_check_relocs,
+  elf_backend_size_relative_relocs,
+  elf_backend_finish_relative_relocs,
   elf_backend_check_directives,
   elf_backend_notice_as_needed,
   elf_backend_adjust_dynamic_symbol,
-- 
2.33.1


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 07/10] elf: Support DT_RELR in linker tests
  2022-01-07 19:06 [PATCH 0/10] ld: Implement DT_RELR for x86 H.J. Lu
                   ` (5 preceding siblings ...)
  2022-01-07 19:06 ` [PATCH 06/10] elf: Add size_relative_relocs and finish_relative_relocs H.J. Lu
@ 2022-01-07 19:06 ` H.J. Lu
  2022-01-08  2:42   ` Fangrui Song
  2022-01-07 19:06 ` [PATCH 08/10] x86: Add DT_RELR support H.J. Lu
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 31+ messages in thread
From: H.J. Lu @ 2022-01-07 19:06 UTC (permalink / raw)
  To: binutils; +Cc: Nick Clifton, Alan Modra, libc-alpha

Allow eabling and disabling DT_RELR in linker tests.  Disable DT_RELR in
linker tests which don't expect DT_RELR in linker outputs.

binutils/

	* testsuite/lib/binutils-common.exp (run_dump_test): Make
	DT_RELR_LDFLAGS and NO_DT_RELR_LDFLAGS global.

ld/

	* testsuite/config/default.exp (DT_RELR_LDFLAGS): New.
	(DT_RELR_CC_LDFLAGS): Likewise.
	(NO_DT_RELR_LDFLAGS): Likewise.
	(NO_DT_RELR_CC_LDFLAGS): Likewise.
	* testsuite/ld-elf/shared.exp: Pass $NO_DT_RELR_LDFLAGS to
	linker for some tests.
	* testsuite/ld-i386/export-class.exp: Likewise.
	* testsuite/ld-i386/i386.exp: Likewise.
	* testsuite/ld-i386/ibt-plt-2a.d: Pass $NO_DT_RELR_LDFLAGS to
	linker.
	* testsuite/ld-i386/ibt-plt-3a.d: Likewise.
	* testsuite/ld-i386/ibt-plt-3c.d: Likewise.
	* testsuite/ld-i386/report-reloc-1.d: Likewise.
	* testsuite/ld-ifunc/ifunc-2-i386-now.d: Likewise.
	* testsuite/ld-ifunc/ifunc-2-local-i386-now.d: Likewise.
	* testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d: Likewise.
	* testsuite/ld-ifunc/ifunc-2-x86-64-now.d: Likewise.
	* testsuite/ld-ifunc/pr17154-x86-64.d: Likewise.
	* testsuite/ld-x86-64/bnd-branch-1-now.d: Likewise.
	* testsuite/ld-x86-64/bnd-ifunc-1-now.d: Likewise.
	* testsuite/ld-x86-64/bnd-ifunc-2-now.d: Likewise.
	* testsuite/ld-x86-64/bnd-ifunc-2.d: Likewise.
	* testsuite/ld-x86-64/bnd-plt-1-now.d: Likewise.
	* testsuite/ld-x86-64/bnd-plt-1.d: Likewise.
	* testsuite/ld-x86-64/ibt-plt-2a-x32.d: Likewise.
	* testsuite/ld-x86-64/ibt-plt-2a.d: Likewise.
	* testsuite/ld-x86-64/ibt-plt-3a-x32.d: Likewise.
	* testsuite/ld-x86-64/ibt-plt-3a.d: Likewise.
	* testsuite/ld-x86-64/ilp32-4.d: Likewise.
	* testsuite/ld-x86-64/load1c.d: Likewise.
	* testsuite/ld-x86-64/load1d.d: Likewise.
	* testsuite/ld-x86-64/pr13082-2b.d: Likewise.
	* testsuite/ld-x86-64/pr14207.d: Likewise.
	* testsuite/ld-x86-64/pr18176.d: Likewise.
	* testsuite/ld-x86-64/pr19162.d: Likewise.
	* testsuite/ld-x86-64/pr19636-2d.d: Likewise.
	* testsuite/ld-x86-64/pr19636-2l.d: Likewise.
	* testsuite/ld-x86-64/pr20253-1d.d: Likewise.
	* testsuite/ld-x86-64/pr20253-1f.d: Likewise.
	* testsuite/ld-x86-64/pr20253-1j.d: Likewise.
	* testsuite/ld-x86-64/pr20253-1l.d: Likewise.
	* testsuite/ld-x86-64/report-reloc-1-x32.d: Likewise.
	* testsuite/ld-x86-64/report-reloc-1.d: Likewise.
	* testsuite/ld-x86-64/export-class.exp (x86_64_export_class_test):
	Pass $NO_DT_RELR_LDFLAGS to linker.
	* testsuite/ld-x86-64/x86-64.exp: Pass $NO_DT_RELR_LDFLAGS to
	linker for some tests.
---
 binutils/testsuite/lib/binutils-common.exp    |  1 +
 ld/testsuite/config/default.exp               | 16 +++++
 ld/testsuite/ld-elf/shared.exp                |  3 +-
 ld/testsuite/ld-i386/export-class.exp         |  2 +-
 ld/testsuite/ld-i386/i386.exp                 | 20 ++++--
 ld/testsuite/ld-i386/ibt-plt-2a.d             |  2 +-
 ld/testsuite/ld-i386/ibt-plt-3a.d             |  2 +-
 ld/testsuite/ld-i386/ibt-plt-3c.d             |  2 +-
 ld/testsuite/ld-i386/report-reloc-1.d         |  2 +-
 ld/testsuite/ld-ifunc/ifunc-2-i386-now.d      |  2 +-
 .../ld-ifunc/ifunc-2-local-i386-now.d         |  2 +-
 .../ld-ifunc/ifunc-2-local-x86-64-now.d       |  2 +-
 ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d    |  2 +-
 ld/testsuite/ld-ifunc/pr17154-x86-64-now.d    |  2 +-
 ld/testsuite/ld-ifunc/pr17154-x86-64.d        |  2 +-
 ld/testsuite/ld-x86-64/bnd-branch-1-now.d     |  2 +-
 ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d      |  2 +-
 ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d      |  2 +-
 ld/testsuite/ld-x86-64/bnd-ifunc-2.d          |  2 +-
 ld/testsuite/ld-x86-64/bnd-plt-1-now.d        |  2 +-
 ld/testsuite/ld-x86-64/bnd-plt-1.d            |  2 +-
 ld/testsuite/ld-x86-64/export-class.exp       |  3 +-
 ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d       |  2 +-
 ld/testsuite/ld-x86-64/ibt-plt-2a.d           |  2 +-
 ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d       |  2 +-
 ld/testsuite/ld-x86-64/ibt-plt-3a.d           |  2 +-
 ld/testsuite/ld-x86-64/ilp32-4.d              |  2 +-
 ld/testsuite/ld-x86-64/load1c.d               |  2 +-
 ld/testsuite/ld-x86-64/load1d.d               |  2 +-
 ld/testsuite/ld-x86-64/pr13082-2b.d           |  2 +-
 ld/testsuite/ld-x86-64/pr14207.d              |  2 +-
 ld/testsuite/ld-x86-64/pr18176.d              |  2 +-
 ld/testsuite/ld-x86-64/pr19162.d              |  2 +-
 ld/testsuite/ld-x86-64/pr19636-2d.d           |  2 +-
 ld/testsuite/ld-x86-64/pr19636-2l.d           |  2 +-
 ld/testsuite/ld-x86-64/pr20253-1d.d           |  2 +-
 ld/testsuite/ld-x86-64/pr20253-1f.d           |  2 +-
 ld/testsuite/ld-x86-64/pr20253-1j.d           |  2 +-
 ld/testsuite/ld-x86-64/pr20253-1l.d           |  2 +-
 ld/testsuite/ld-x86-64/report-reloc-1-x32.d   |  2 +-
 ld/testsuite/ld-x86-64/report-reloc-1.d       |  2 +-
 ld/testsuite/ld-x86-64/x86-64.exp             | 65 ++++++++++++-------
 42 files changed, 114 insertions(+), 66 deletions(-)

diff --git a/binutils/testsuite/lib/binutils-common.exp b/binutils/testsuite/lib/binutils-common.exp
index 0e0ba8e5aee..88fdc1a71c7 100644
--- a/binutils/testsuite/lib/binutils-common.exp
+++ b/binutils/testsuite/lib/binutils-common.exp
@@ -855,6 +855,7 @@ proc run_dump_test { name {extra_options {}} } {
     global ELFEDIT ELFEDITFLAGS LD LDFLAGS NM NMFLAGS OBJCOPY OBJCOPYFLAGS
     global OBJDUMP OBJDUMPFLAGS READELF READELFFLAGS STRIP STRIPFLAGS
     global copyfile env runtests srcdir subdir verbose
+    global DT_RELR_LDFLAGS NO_DT_RELR_LDFLAGS
 
     if [string match "*/*" $name] {
 	set file $name
diff --git a/ld/testsuite/config/default.exp b/ld/testsuite/config/default.exp
index c988d5d2924..52e75048ede 100644
--- a/ld/testsuite/config/default.exp
+++ b/ld/testsuite/config/default.exp
@@ -313,6 +313,22 @@ if ![info exists LDFLAGS] then {
     set LDFLAGS {}
 }
 
+if { ![info exists DT_RELR_LDFLAGS] } then {
+    set DT_RELR_LDFLAGS "-z pack-relative-relocs"
+}
+
+if { ![info exists DT_RELR_CC_LDFLAGS] } then {
+    set DT_RELR_CC_LDFLAGS "-Wl,-z,pack-relative-relocs"
+}
+
+if { ![info exists NO_DT_RELR_LDFLAGS] } then {
+    set NO_DT_RELR_LDFLAGS "-z nopack-relative-relocs"
+}
+
+if { ![info exists NO_DT_RELR_CC_LDFLAGS] } then {
+    set NO_DT_RELR_CC_LDFLAGS "-Wl,-z,nopack-relative-relocs"
+}
+
 # Set LD_CLASS to "64bit" for a 64-bit *host* linker.
 if { ![info exists LD_CLASS] } then {
     set REAL_LD [findfile $base_dir/.libs/ld-new .libs/ld-new $LD [transform ld]]
diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
index cb3b8c15cfc..1381544e6f8 100644
--- a/ld/testsuite/ld-elf/shared.exp
+++ b/ld/testsuite/ld-elf/shared.exp
@@ -452,7 +452,8 @@ setup_xfail mips*-*-* bfin-*-*
 clear_xfail bfin-*-linux*
 run_ld_link_tests [list \
     [list "-Bsymbolic-functions" \
-	"-shared -Bsymbolic-functions" "" "$AFLAGS_PIC" \
+	"-shared -Bsymbolic-functions $NO_DT_RELR_LDFLAGS" \
+	"" "$AFLAGS_PIC" \
 	{symbolic-func.s} {{readelf {-r --wide} symbolic-func.r}} \
 	"symbolic-func.so"] \
 ]
diff --git a/ld/testsuite/ld-i386/export-class.exp b/ld/testsuite/ld-i386/export-class.exp
index 47b2c0f0056..04bc6a0d836 100644
--- a/ld/testsuite/ld-i386/export-class.exp
+++ b/ld/testsuite/ld-i386/export-class.exp
@@ -74,7 +74,7 @@ run_ld_link_tests [list \
 run_ld_link_tests [list \
     [list \
 	"$testname (final shared object)" \
-	"-shared -Tdata=0x12340000 tmpdir/i386-export-class-ref-r.o tmpdir/i386-export-class-lib.so" "" \
+	"-shared $NO_DT_RELR_LDFLAGS -Tdata=0x12340000 tmpdir/i386-export-class-ref-r.o tmpdir/i386-export-class-lib.so" "" \
 	"" \
 	{ ../ld-elf/export-class-dep.s ../ld-elf/export-class-def.s } \
 	{ \
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 3ed6e42e78f..c2d8d8268c3 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -177,12 +177,6 @@ set i386tests {
      {{readelf -Ssrl tlsbindesc.rd} {objdump -drj.text tlsbindesc.dd}
       {objdump -sj.got tlsbindesc.sd} {objdump -sj.tdata tlsbindesc.td}}
       "tlsbindesc"}
-    {"TLS -fno-pic -shared"
-     "-shared -melf_i386 --no-ld-generated-unwind-info -z notext \
-      -z noseparate-code --hash-style=sysv" ""
-     "--32" {tlsnopic1.s tlsnopic2.s}
-     {{readelf -Ssrl tlsnopic.rd} {objdump -drj.text tlsnopic.dd}
-      {objdump -sj.got tlsnopic.sd}} "libtlsnopic.so"}
     {"TLS with global dynamic and descriptors"
      "-shared -melf_i386 --no-ld-generated-unwind-info \
       -z noseparate-code --hash-style=sysv" ""
@@ -293,6 +287,20 @@ iamcu_tests
 
 run_ld_link_tests $i386tests
 
+run_ld_link_tests [list \
+    [list \
+	"TLS -fno-pic -shared" \
+	"-shared -melf_i386 --no-ld-generated-unwind-info -z notext \
+	 -z noseparate-code --hash-style=sysv $NO_DT_RELR_LDFLAGS" \
+	"" "--32" \
+	{tlsnopic1.s tlsnopic2.s} \
+	{{readelf -Ssrl tlsnopic.rd} \
+	 {objdump -drj.text tlsnopic.dd} \
+	 {objdump -sj.got tlsnopic.sd}} \
+	"libtlsnopic.so" \
+    ] \
+]
+
 run_dump_test "abs"
 run_dump_test "pcrel8"
 run_dump_test "pcrel16"
diff --git a/ld/testsuite/ld-i386/ibt-plt-2a.d b/ld/testsuite/ld-i386/ibt-plt-2a.d
index 42aa2ce7410..98b6fb9a5aa 100644
--- a/ld/testsuite/ld-i386/ibt-plt-2a.d
+++ b/ld/testsuite/ld-i386/ibt-plt-2a.d
@@ -1,6 +1,6 @@
 #source: ibt-plt-2.s
 #as: --32
-#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code
+#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-i386/ibt-plt-3a.d b/ld/testsuite/ld-i386/ibt-plt-3a.d
index b357a74a33b..91f2023db35 100644
--- a/ld/testsuite/ld-i386/ibt-plt-3a.d
+++ b/ld/testsuite/ld-i386/ibt-plt-3a.d
@@ -1,6 +1,6 @@
 #source: ibt-plt-3.s
 #as: --32
-#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code
+#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-i386/ibt-plt-3c.d b/ld/testsuite/ld-i386/ibt-plt-3c.d
index b357a74a33b..91f2023db35 100644
--- a/ld/testsuite/ld-i386/ibt-plt-3c.d
+++ b/ld/testsuite/ld-i386/ibt-plt-3c.d
@@ -1,6 +1,6 @@
 #source: ibt-plt-3.s
 #as: --32
-#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code
+#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-i386/report-reloc-1.d b/ld/testsuite/ld-i386/report-reloc-1.d
index 51fbbd8d105..162161592a1 100644
--- a/ld/testsuite/ld-i386/report-reloc-1.d
+++ b/ld/testsuite/ld-i386/report-reloc-1.d
@@ -1,6 +1,6 @@
 #source: report-reloc-1.s
 #as: --32
-#ld: -pie -melf_i386 -z report-relative-reloc
+#ld: -pie -melf_i386 -z report-relative-reloc $NO_DT_RELR_LDFLAGS
 #warning_output: report-reloc-1.l
 #readelf: -r --wide
 
diff --git a/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d b/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d
index 0d3f7b80d06..aae24b2809d 100644
--- a/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d
+++ b/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d
@@ -1,5 +1,5 @@
 #source: ifunc-2-i386.s
-#ld: -z now -m elf_i386 -shared --hash-style=sysv -z noseparate-code
+#ld: -z now -m elf_i386 -shared --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
 #as: --32
 #objdump: -dw
 #target: x86_64-*-* i?86-*-*
diff --git a/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d b/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d
index 48d2084d38f..86083c12a08 100644
--- a/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d
+++ b/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d
@@ -1,5 +1,5 @@
 #source: ifunc-2-local-i386.s
-#ld: -z now -m elf_i386 -shared --hash-style=sysv -z noseparate-code
+#ld: -z now -m elf_i386 -shared --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
 #as: --32
 #objdump: -dw
 #target: x86_64-*-* i?86-*-*
diff --git a/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d b/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d
index 14866a8f6cc..be3da08e12b 100644
--- a/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d
+++ b/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d
@@ -1,6 +1,6 @@
 #source: ifunc-2-local-x86-64.s
 #as: --64
-#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 #target: x86_64-*-*
 
diff --git a/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d b/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d
index 1cd60941ac0..b504f9adedd 100644
--- a/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d
+++ b/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d
@@ -1,6 +1,6 @@
 #source: ifunc-2-x86-64.s
 #as: --64
-#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 #target: x86_64-*-*
 
diff --git a/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d b/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d
index 4cc1dc206d5..f6920272b63 100644
--- a/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d
+++ b/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d
@@ -1,6 +1,6 @@
 #source: pr17154-x86.s
 #as: --64
-#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 #target: x86_64-*-*
 
diff --git a/ld/testsuite/ld-ifunc/pr17154-x86-64.d b/ld/testsuite/ld-ifunc/pr17154-x86-64.d
index 9fb23d410e3..90918426ee5 100644
--- a/ld/testsuite/ld-ifunc/pr17154-x86-64.d
+++ b/ld/testsuite/ld-ifunc/pr17154-x86-64.d
@@ -1,6 +1,6 @@
 #source: pr17154-x86.s
 #as: --64
-#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 #target: x86_64-*-*
 
diff --git a/ld/testsuite/ld-x86-64/bnd-branch-1-now.d b/ld/testsuite/ld-x86-64/bnd-branch-1-now.d
index b7bc4e526cc..b1bcea3cf4c 100644
--- a/ld/testsuite/ld-x86-64/bnd-branch-1-now.d
+++ b/ld/testsuite/ld-x86-64/bnd-branch-1-now.d
@@ -1,6 +1,6 @@
 #source: bnd-branch-1.s -mx86-used-note=no
 #as: --64
-#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d b/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d
index 15ecfe1cc50..86ba30a46d5 100644
--- a/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d
+++ b/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d
@@ -1,6 +1,6 @@
 #source: bnd-ifunc-1.s
 #as: --64 -madd-bnd-prefix -mx86-used-note=no
-#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d b/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d
index 211d72d2335..fa7ec07aaf0 100644
--- a/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d
+++ b/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d
@@ -1,6 +1,6 @@
 #source: bnd-ifunc-2.s
 #as: --64 -madd-bnd-prefix -mx86-used-note=no
-#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/bnd-ifunc-2.d b/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
index f80ba15aa35..36534b14feb 100644
--- a/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
+++ b/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
@@ -1,5 +1,5 @@
 #as: --64 -madd-bnd-prefix -mx86-used-note=no
-#ld: -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 #...
diff --git a/ld/testsuite/ld-x86-64/bnd-plt-1-now.d b/ld/testsuite/ld-x86-64/bnd-plt-1-now.d
index 24e28210a0a..47289a04f43 100644
--- a/ld/testsuite/ld-x86-64/bnd-plt-1-now.d
+++ b/ld/testsuite/ld-x86-64/bnd-plt-1-now.d
@@ -1,6 +1,6 @@
 #source: bnd-branch-1.s
 #as: --64 -mx86-used-note=no
-#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/bnd-plt-1.d b/ld/testsuite/ld-x86-64/bnd-plt-1.d
index 0df32555c18..f047da897ce 100644
--- a/ld/testsuite/ld-x86-64/bnd-plt-1.d
+++ b/ld/testsuite/ld-x86-64/bnd-plt-1.d
@@ -1,6 +1,6 @@
 #source: bnd-branch-1.s
 #as: --64 -mx86-used-note=no
-#ld: -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/export-class.exp b/ld/testsuite/ld-x86-64/export-class.exp
index 26896d1ca87..14c2d240fac 100644
--- a/ld/testsuite/ld-x86-64/export-class.exp
+++ b/ld/testsuite/ld-x86-64/export-class.exp
@@ -31,6 +31,7 @@ if { ![istarget x86_64*-*-linux*] } {
 }
 
 proc x86_64_export_class_test { abi flag emul } {
+    global NO_DT_RELR_LDFLAGS
 
     set testname "x86-64 $abi symbol export class test"
 
@@ -75,7 +76,7 @@ proc x86_64_export_class_test { abi flag emul } {
     run_ld_link_tests [list \
 	[list \
 	    "$testname (final shared object)" \
-	    "$LDFLAGS -shared -Tdata=0x12340000 tmpdir/x86-64-$abi-export-class-ref-r.o tmpdir/x86-64-$abi-export-class-lib.so" "" \
+	    "$LDFLAGS $NO_DT_RELR_LDFLAGS -shared -Tdata=0x12340000 tmpdir/x86-64-$abi-export-class-ref-r.o tmpdir/x86-64-$abi-export-class-lib.so" "" \
 	    "$AFLAGS" \
 	    { ../ld-elf/export-class-dep.s ../ld-elf/export-class-def.s } \
 	    [list \
diff --git a/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d
index a19cece98e8..23e31e62f55 100644
--- a/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d
+++ b/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d
@@ -1,6 +1,6 @@
 #source: ibt-plt-2.s
 #as: --x32
-#ld: -shared -m elf32_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -shared -m elf32_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/ibt-plt-2a.d b/ld/testsuite/ld-x86-64/ibt-plt-2a.d
index 92785929092..adbbf62e84d 100644
--- a/ld/testsuite/ld-x86-64/ibt-plt-2a.d
+++ b/ld/testsuite/ld-x86-64/ibt-plt-2a.d
@@ -1,6 +1,6 @@
 #source: ibt-plt-2.s
 #as: --64 -defsym __64_bit__=1
-#ld: -shared -m elf_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -shared -m elf_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d
index d6f8bb3afbe..f52b1cc796f 100644
--- a/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d
+++ b/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d
@@ -1,6 +1,6 @@
 #source: ibt-plt-3.s
 #as: --x32
-#ld: -shared -m elf32_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -shared -m elf32_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/ibt-plt-3a.d b/ld/testsuite/ld-x86-64/ibt-plt-3a.d
index 9c15ed4f928..8bd8851ea73 100644
--- a/ld/testsuite/ld-x86-64/ibt-plt-3a.d
+++ b/ld/testsuite/ld-x86-64/ibt-plt-3a.d
@@ -1,6 +1,6 @@
 #source: ibt-plt-3.s
 #as: --64 -defsym __64_bit__=1
-#ld: -shared -m elf_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -shared -m elf_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/ilp32-4.d b/ld/testsuite/ld-x86-64/ilp32-4.d
index 34be012056e..ad5c9cdf858 100644
--- a/ld/testsuite/ld-x86-64/ilp32-4.d
+++ b/ld/testsuite/ld-x86-64/ilp32-4.d
@@ -1,5 +1,5 @@
 #as: --x32
-#ld: -m elf32_x86_64 -shared --no-ld-generated-unwind-info --hash-style=sysv
+#ld: -m elf32_x86_64 -shared --no-ld-generated-unwind-info --hash-style=sysv $NO_DT_RELR_LDFLAGS
 #readelf: -d -S --wide
 #target: x86_64-*-linux*
 
diff --git a/ld/testsuite/ld-x86-64/load1c.d b/ld/testsuite/ld-x86-64/load1c.d
index db9c69fadbf..7404c7093b4 100644
--- a/ld/testsuite/ld-x86-64/load1c.d
+++ b/ld/testsuite/ld-x86-64/load1c.d
@@ -1,6 +1,6 @@
 #source: load1.s
 #as: --64
-#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/load1d.d b/ld/testsuite/ld-x86-64/load1d.d
index 7ccae532f27..1b474a375c7 100644
--- a/ld/testsuite/ld-x86-64/load1d.d
+++ b/ld/testsuite/ld-x86-64/load1d.d
@@ -1,6 +1,6 @@
 #source: load1.s
 #as: --x32
-#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/pr13082-2b.d b/ld/testsuite/ld-x86-64/pr13082-2b.d
index c218eafe34c..71c44fc0ee5 100644
--- a/ld/testsuite/ld-x86-64/pr13082-2b.d
+++ b/ld/testsuite/ld-x86-64/pr13082-2b.d
@@ -1,7 +1,7 @@
 #source: pr13082-2.s
 #name: PR ld/13082-2 (b)
 #as: --x32
-#ld: -pie -melf32_x86_64
+#ld: -pie -melf32_x86_64 $NO_DT_RELR_LDFLAGS
 #readelf: -r --wide
 
 Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entry:
diff --git a/ld/testsuite/ld-x86-64/pr14207.d b/ld/testsuite/ld-x86-64/pr14207.d
index f330600b916..e3af36146c6 100644
--- a/ld/testsuite/ld-x86-64/pr14207.d
+++ b/ld/testsuite/ld-x86-64/pr14207.d
@@ -1,6 +1,6 @@
 #name: PR ld/14207
 #as: --64
-#ld: -melf_x86_64 -shared -z relro -z now --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -melf_x86_64 -shared -z relro -z now --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #readelf: -l --wide
 #target: x86_64-*-linux*
 
diff --git a/ld/testsuite/ld-x86-64/pr18176.d b/ld/testsuite/ld-x86-64/pr18176.d
index 4e3ad9ff08d..a99ff15ac6b 100644
--- a/ld/testsuite/ld-x86-64/pr18176.d
+++ b/ld/testsuite/ld-x86-64/pr18176.d
@@ -1,6 +1,6 @@
 #name: PR ld/18176
 #as: --64
-#ld: -melf_x86_64 -shared -z relro -T pr18176.t -z max-page-size=0x200000 -z common-page-size=0x1000
+#ld: -melf_x86_64 -shared -z relro -T pr18176.t -z max-page-size=0x200000 -z common-page-size=0x1000 $NO_DT_RELR_LDFLAGS
 #readelf: -l --wide
 #target: x86_64-*-linux*
 
diff --git a/ld/testsuite/ld-x86-64/pr19162.d b/ld/testsuite/ld-x86-64/pr19162.d
index 2d51dabe729..f458853d8e5 100644
--- a/ld/testsuite/ld-x86-64/pr19162.d
+++ b/ld/testsuite/ld-x86-64/pr19162.d
@@ -1,7 +1,7 @@
 #source: pr19162a.s
 #source: pr19162b.s
 #as: --64
-#ld: -melf_x86_64 -shared -z noseparate-code -z max-page-size=0x200000 -z common-page-size=0x1000 --hash-style=sysv
+#ld: -melf_x86_64 -shared -z noseparate-code -z max-page-size=0x200000 -z common-page-size=0x1000 --hash-style=sysv $NO_DT_RELR_LDFLAGS
 #readelf: -l --wide
 #target: x86_64-*-linux*
 
diff --git a/ld/testsuite/ld-x86-64/pr19636-2d.d b/ld/testsuite/ld-x86-64/pr19636-2d.d
index 3bd33a9a915..092992be9d4 100644
--- a/ld/testsuite/ld-x86-64/pr19636-2d.d
+++ b/ld/testsuite/ld-x86-64/pr19636-2d.d
@@ -1,6 +1,6 @@
 #source: pr19636-2.s
 #as: --64 -mrelax-relocations=no
-#ld: -pie -m elf_x86_64 --no-dynamic-linker --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -pie -m elf_x86_64 --no-dynamic-linker --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/pr19636-2l.d b/ld/testsuite/ld-x86-64/pr19636-2l.d
index 1b894b3e97c..8c23c0b7411 100644
--- a/ld/testsuite/ld-x86-64/pr19636-2l.d
+++ b/ld/testsuite/ld-x86-64/pr19636-2l.d
@@ -1,6 +1,6 @@
 #source: pr19636-2.s
 #as: --64 -mrelax-relocations=no
-#ld: -pie -m elf_x86_64 --no-dynamic-linker --hash-style=sysv -z dynamic-undefined-weak -z max-page-size=0x200000 -z noseparate-code
+#ld: -pie -m elf_x86_64 --no-dynamic-linker --hash-style=sysv -z dynamic-undefined-weak -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 #warning: -z dynamic-undefined-weak ignored
 
diff --git a/ld/testsuite/ld-x86-64/pr20253-1d.d b/ld/testsuite/ld-x86-64/pr20253-1d.d
index f9f03ba8403..057577bdc57 100644
--- a/ld/testsuite/ld-x86-64/pr20253-1d.d
+++ b/ld/testsuite/ld-x86-64/pr20253-1d.d
@@ -1,6 +1,6 @@
 #source: pr20253-1.s
 #as: --64
-#ld: -pie -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -pie -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/pr20253-1f.d b/ld/testsuite/ld-x86-64/pr20253-1f.d
index 6666bcaf147..479db8202e8 100644
--- a/ld/testsuite/ld-x86-64/pr20253-1f.d
+++ b/ld/testsuite/ld-x86-64/pr20253-1f.d
@@ -1,6 +1,6 @@
 #source: pr20253-1.s
 #as: --64
-#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/pr20253-1j.d b/ld/testsuite/ld-x86-64/pr20253-1j.d
index 88c9715ad75..20176a2d357 100644
--- a/ld/testsuite/ld-x86-64/pr20253-1j.d
+++ b/ld/testsuite/ld-x86-64/pr20253-1j.d
@@ -1,6 +1,6 @@
 #source: pr20253-1.s
 #as: --x32
-#ld: -pie -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -pie -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/pr20253-1l.d b/ld/testsuite/ld-x86-64/pr20253-1l.d
index 7428a721b16..4b179077dec 100644
--- a/ld/testsuite/ld-x86-64/pr20253-1l.d
+++ b/ld/testsuite/ld-x86-64/pr20253-1l.d
@@ -1,6 +1,6 @@
 #source: pr20253-1.s
 #as: --x32
-#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
+#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
 #objdump: -dw
 
 .*: +file format .*
diff --git a/ld/testsuite/ld-x86-64/report-reloc-1-x32.d b/ld/testsuite/ld-x86-64/report-reloc-1-x32.d
index c66f956c473..63fe7b1bb8a 100644
--- a/ld/testsuite/ld-x86-64/report-reloc-1-x32.d
+++ b/ld/testsuite/ld-x86-64/report-reloc-1-x32.d
@@ -1,6 +1,6 @@
 #source: report-reloc-1.s
 #as: --x32
-#ld: -pie -melf32_x86_64 -z report-relative-reloc
+#ld: -pie -melf32_x86_64 -z report-relative-reloc $NO_DT_RELR_LDFLAGS
 #warning_output: report-reloc-1.l
 #readelf: -r --wide
 
diff --git a/ld/testsuite/ld-x86-64/report-reloc-1.d b/ld/testsuite/ld-x86-64/report-reloc-1.d
index 1b5f91fdd3f..69f164c9434 100644
--- a/ld/testsuite/ld-x86-64/report-reloc-1.d
+++ b/ld/testsuite/ld-x86-64/report-reloc-1.d
@@ -1,6 +1,6 @@
 #source: report-reloc-1.s
 #as: --64
-#ld: -pie -melf_x86_64 -z report-relative-reloc
+#ld: -pie -melf_x86_64 -z report-relative-reloc $NO_DT_RELR_LDFLAGS
 #warning_output: report-reloc-1.l
 #readelf: -r --wide
 
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index c100879397e..b4048128057 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -45,28 +45,6 @@ set x86_64tests {
     {"basic PLT generation"
      "-melf_x86_64 tmpdir/libpltlib.so" "" "--64" {plt.s}
      {{objdump -drj.plt plt.pd}} "plt"}
-    {"TLS -fpic -shared transitions"
-     "-shared -melf_x86_64 --no-ld-generated-unwind-info \
-      -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv" ""
-     "--64" {tlspic1.s tlspic2.s}
-     {{readelf -WSsrl tlspic.rd} {objdump -drj.text\ -Mintel64 tlspic.dd}
-      {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
-      "libtlspic.so"}
-    {"TLS -fpic -shared transitions with r15 as GOT base"
-     "-shared -melf_x86_64 --no-ld-generated-unwind-info \
-      -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv" ""
-     "--64 -mrelax-relocations=yes"
-     {tlspic3.s tlspic2.s}
-     {{readelf -WSsrl tlspic2.rd} {objdump -drj.text\ -Mintel64 tlspic2.dd}
-      {objdump -sj.got tlspic2.sd} {objdump -sj.tdata tlspic2.td}}
-      "libtlspic2.so"}
-    {"TLS descriptor -fpic -shared transitions"
-     "-shared -melf_x86_64 --no-ld-generated-unwind-info \
-      -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv" ""
-     "--64" {tlsdesc.s tlspic2.s}
-     {{readelf -WSsrld tlsdesc.rd} {objdump -drj.text tlsdesc.dd}
-      {objdump "-s -j.got -j.got.plt" tlsdesc.sd} {objdump -sj.tdata tlsdesc.td}
-      {objdump -drj.plt tlsdesc.pd}} "libtlsdesc.so"}
     {"Helper shared library" "-shared -melf_x86_64" ""
      "--64" {tlslib.s} {} "libtlslib.so"}
     {"TLS -fpic and -fno-pic exec transitions"
@@ -240,6 +218,49 @@ set x86_64tests {
 
 run_ld_link_tests $x86_64tests
 
+run_ld_link_tests [list \
+    [list \
+	"TLS -fpic -shared transitions" \
+	"-shared -melf_x86_64 --no-ld-generated-unwind-info \
+	 -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv \
+	 $NO_DT_RELR_LDFLAGS" \
+	"" "--64" \
+	{tlspic1.s tlspic2.s} \
+	{{readelf -WSsrl tlspic.rd} \
+	 {objdump {-drj.text -Mintel64} tlspic.dd} \
+	 {objdump -sj.got tlspic.sd} \
+	 {objdump -sj.tdata tlspic.td}} \
+	"libtlspic.so" \
+    ] \
+    [list \
+	"TLS -fpic -shared transitions with r15 as GOT base" \
+	"-shared -melf_x86_64 --no-ld-generated-unwind-info \
+	 -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv \
+	 $NO_DT_RELR_LDFLAGS" \
+	 "" "--64 -mrelax-relocations=yes" \
+	{tlspic3.s tlspic2.s} \
+	{{readelf -WSsrl tlspic2.rd} \
+	 {objdump {-drj.text -Mintel64} tlspic2.dd} \
+	 {objdump -sj.got tlspic2.sd} \
+	 {objdump -sj.tdata tlspic2.td}} \
+	"libtlspic2.so" \
+    ] \
+    [list \
+	"TLS descriptor -fpic -shared transitions" \
+	"-shared -melf_x86_64 --no-ld-generated-unwind-info \
+	 -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv \
+	 $NO_DT_RELR_LDFLAGS" \
+	"" "--64" \
+	{tlsdesc.s tlspic2.s} \
+	{{readelf -WSsrld tlsdesc.rd} \
+	 {objdump -drj.text tlsdesc.dd} \
+	 {objdump {-s -j.got -j.got.plt} tlsdesc.sd} \
+	 {objdump -sj.tdata tlsdesc.td} \
+	 {objdump -drj.plt tlsdesc.pd}} \
+	 "libtlsdesc.so" \
+    ] \
+]
+
 set test_name "Mixed x86_64 and i386 input test 1"
 set test mixed1
 if { ![ld_link $ld tmpdir/$test "-m$emul tmpdir/${test}a.o tmpdir/${test}b.o"] } {
-- 
2.33.1


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 08/10] x86: Add DT_RELR support
  2022-01-07 19:06 [PATCH 0/10] ld: Implement DT_RELR for x86 H.J. Lu
                   ` (6 preceding siblings ...)
  2022-01-07 19:06 ` [PATCH 07/10] elf: Support DT_RELR in linker tests H.J. Lu
@ 2022-01-07 19:06 ` H.J. Lu
  2022-01-07 19:06 ` [PATCH 09/10] ld: Add simple DT_RELR tests H.J. Lu
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-07 19:06 UTC (permalink / raw)
  To: binutils; +Cc: Nick Clifton, Alan Modra, libc-alpha

DT_RELR is implemented with linker relaxation:

1. During linker relaxation, we scan input relocations with the same
logic in relocate_section to determine if a relative relocation should
be generated and save the relative relocation candidate information for
sizing the DT_RELR section later after all symbols addresses can be
determined.  For these relative relocations which can't be placed in
the DT_RELR section, they will be placed in the rela.dyn/rel.dyn
section.
2. When DT_RELR is enabled, _bfd_elf_map_sections_to_segments calls a
backend function to size the DT_RELR section which will compute the
DT_RELR section size and tell ldelf_map_segments to layout sections
again when the DT_RELR section size has been increased.
3. After regular symbol processing is finished, bfd_elf_final_link calls
a backend function to finish the DT_RELR section.

	* elf32-i386.c (elf_i386_scan_relocs): Set SEC_ELF_REVERSE_COPY
	on input section for DT_RELR.
	(elf_i386_relocate_section): Don't generate relative relocation
	when DT_RELR is enabled.
	* elf64-x86-64.c (elf_x86_64_scan_relocs): Set
	SEC_ELF_REVERSE_COPY on input section for DT_RELR.
	(elf_x86_64_relocate_section): Don't generate relative relocation
	when DT_RELR is enabled.
	* elfxx-x86.c (_bfd_x86_elf_link_hash_table_create): Initialize
	relative_r_type, relative_r_name, elf_append_reloc,
	elf_write_addend and elf_write_addend_in_got.
	(elf_x86_relative_reloc_record_add): New function.
	(_bfd_x86_elf_link_relax_section): Likewise.
	(elf64_dt_relr_bitmap_add): Likewise.
	(elf32_dt_relr_bitmap_add): Likewise.
	(_bfd_elf32_write_addend): Likewise.
	(_bfd_elf64_write_addend): Likewise.
	(elf_x86_size_or_finish_relative_reloc): Likewise.
	(elf_x86_compute_dl_relr_bitmap): Likewise.
	(elf_x86_write_dl_relr_bitmap): Likewise.
	(elf_x86_relative_reloc_compare ): Likewise.
	(_bfd_elf_x86_size_relative_relocs): Likewise.
	(_bfd_elf_x86_finish_relative_relocs): Likewise.
	(_bfd_x86_elf_size_dynamic_sections): Skip the .relr.dyn section.
	(_bfd_x86_elf_finish_dynamic_sections): Convert 3 spare dynamic
	tags to DT_RELR, DT_RELRSZ and for compact relative relocation.
	* elfxx-x86.h (X86_64_GOT_TYPE_P): New.
	(I386_GOT_TYPE_P): Likewise.
	(X86_GOT_TYPE_P): Likewise.
	(X86_64_RELATIVE_RELOC_TYPE_P): Likewise.
	(I386_RELATIVE_RELOC_TYPE_P): Likewise.
	(X86_RELATIVE_RELOC_TYPE_P): Likewise.
	(X86_LOCAL_GOT_RELATIVE_RELOC_P): Likewise.
	(I386_PCREL_TYPE_P): Likewise.
	(X86_64_PCREL_TYPE_P): Likewise.
	(X86_64_NEED_DYNAMIC_RELOC_TYPE_P): Rewrite.
	(I386_NEED_DYNAMIC_RELOC_TYPE_P): Likewise.
	(GENERATE_DYNAMIC_RELOCATION_P): Also check rel_from_abs.
	(elf_x86_link_hash_entry): Add got_relative_reloc_done.
	(elf_x86_relative_reloc_record): New.
	(elf_x86_relative_reloc_data): Likewise.
	(elf_dt_relr_bitmap): Likewise.
	(elf_x86_link_hash_table): Add dt_relr_bitmap, relative_reloc,
	unaligned_relative_reloc, relative_r_type, relative_r_name,
	elf_append_reloc, elf_write_addend, elf_write_addend_in_got and
	relative_reloc_done.
	(elf_x86_relative_reloc_done): New.
	(relative_reloc_packed): Likewise.
	(_bfd_x86_elf_link_relax_section): Likewise.
	(_bfd_elf_x86_size_relative_relocs): Likewise.
	(_bfd_elf_x86_finish_relative_relocs): Likewise.
	(_bfd_elf32_write_addend): Likewise.
	(_bfd_elf64_write_addend): Likewise.
	(bfd_elf32_bfd_relax_section): Likewise.
	(bfd_elf64_bfd_relax_section): Likewise.
	(elf_backend_size_relative_relocs): Likewise.
	(elf_backend_finish_relative_relocs): Likewise.
	(elf_x86_allocate_local_got_info): Also allocate
	relative_reloc_done.
---
 bfd/elf32-i386.c   |  54 ++-
 bfd/elf64-x86-64.c |  63 ++-
 bfd/elfxx-x86.c    | 937 +++++++++++++++++++++++++++++++++++++++++++++
 bfd/elfxx-x86.h    | 147 ++++++-
 4 files changed, 1161 insertions(+), 40 deletions(-)

diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index d1f61be5044..8e34bf0bcb4 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1456,6 +1456,7 @@ elf_i386_scan_relocs (bfd *abfd,
 		      asection *sec,
 		      const Elf_Internal_Rela *relocs)
 {
+  const struct elf_backend_data *bed;
   struct elf_x86_link_hash_table *htab;
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
@@ -1485,6 +1486,14 @@ elf_i386_scan_relocs (bfd *abfd,
       return false;
     }
 
+  bed = get_elf_backend_data (abfd);
+
+  /* Set SEC_ELF_REVERSE_COPY here so that the correct section offset
+     will be used for DT_RELR.  */
+  if (!_bfd_elf_process_reverse_copy (sec, 4,
+				      bed->s->int_rels_per_ext_rel))
+    return false;
+
   symtab_hdr = &elf_symtab_hdr (abfd);
   sym_hashes = elf_sym_hashes (abfd);
 
@@ -2473,8 +2482,10 @@ elf_i386_relocate_section (bfd *output_bfd,
 		      bfd_put_32 (output_bfd, relocation,
 				  htab->elf.sgot->contents + off);
 		      h->got.offset |= 1;
-
-		      if (GENERATE_RELATIVE_RELOC_P (info, h))
+		      /* NB: Don't generate relative relocation here if
+			 it has been generated by DT_RELR.  */
+		      if (!info->enable_dt_relr
+			  && GENERATE_RELATIVE_RELOC_P (info, h))
 			{
 			  /* PR ld/21402: If this symbol isn't dynamic
 			     in PIC, generate R_386_RELATIVE here.  */
@@ -2504,7 +2515,9 @@ elf_i386_relocate_section (bfd *output_bfd,
 			      htab->elf.sgot->contents + off);
 		  local_got_offsets[r_symndx] |= 1;
 
-		  if (bfd_link_pic (info))
+		  /* NB: Don't generate relative relocation here if it
+		     has been generated by DT_RELR.  */
+		  if (!info->enable_dt_relr && bfd_link_pic (info))
 		    relative_reloc = true;
 		}
 	    }
@@ -2707,6 +2720,7 @@ elf_i386_relocate_section (bfd *output_bfd,
 	    {
 	      Elf_Internal_Rela outrel;
 	      bool skip, relocate;
+	      bool generate_dynamic_reloc = true;
 	      asection *sreloc;
 
 	      /* When generating a shared object, these relocations
@@ -2734,23 +2748,33 @@ elf_i386_relocate_section (bfd *output_bfd,
 		{
 		  /* This symbol is local, or marked to become local.  */
 		  relocate = true;
-		  outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+		  /* NB: Don't generate relative relocation here if it
+		     has been generated by DT_RELR.  */
+		  if (info->enable_dt_relr)
+		    generate_dynamic_reloc = false;
+		  else
+		    {
+		      outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
 
-		  if (htab->params->report_relative_reloc)
-		    _bfd_x86_elf_link_report_relative_reloc
-		      (info, input_section, h, sym, "R_386_RELATIVE",
-		       &outrel);
+		      if (htab->params->report_relative_reloc)
+			_bfd_x86_elf_link_report_relative_reloc
+			  (info, input_section, h, sym, "R_386_RELATIVE",
+			   &outrel);
+		    }
 		}
 
-	      sreloc = elf_section_data (input_section)->sreloc;
-
-	      if (sreloc == NULL || sreloc->contents == NULL)
+	      if (generate_dynamic_reloc)
 		{
-		  r = bfd_reloc_notsupported;
-		  goto check_relocation_error;
-		}
+		  sreloc = elf_section_data (input_section)->sreloc;
 
-	      elf_append_rel (output_bfd, sreloc, &outrel);
+		  if (sreloc == NULL || sreloc->contents == NULL)
+		    {
+		      r = bfd_reloc_notsupported;
+		      goto check_relocation_error;
+		    }
+
+		  elf_append_rel (output_bfd, sreloc, &outrel);
+		}
 
 	      /* If this reloc is against an external symbol, we do
 		 not want to fiddle with the addend.  Otherwise, we
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index ad885f89e11..0842df33c75 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1826,6 +1826,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
 			asection *sec,
 			const Elf_Internal_Rela *relocs)
 {
+  const struct elf_backend_data *bed;
   struct elf_x86_link_hash_table *htab;
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
@@ -1855,6 +1856,14 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
       return false;
     }
 
+  bed = get_elf_backend_data (abfd);
+
+  /* Set SEC_ELF_REVERSE_COPY here so that the correct section offset
+     will be used for DT_RELR.  */
+  if (!_bfd_elf_process_reverse_copy (sec, ABI_64_P (abfd) ? 8 : 4,
+				      bed->s->int_rels_per_ext_rel))
+    return false;
+
   symtab_hdr = &elf_symtab_hdr (abfd);
   sym_hashes = elf_sym_hashes (abfd);
 
@@ -2867,7 +2876,10 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 			 as -1 | 1 still is -1.  */
 		      h->got.offset |= 1;
 
-		      if (GENERATE_RELATIVE_RELOC_P (info, h))
+		      /* NB: Don't generate relative relocation here if
+			 it has been generated by DT_RELR.  */
+		      if (!info->enable_dt_relr
+			  && GENERATE_RELATIVE_RELOC_P (info, h))
 			{
 			  /* If this symbol isn't dynamic in PIC,
 			     generate R_X86_64_RELATIVE here.  */
@@ -2899,8 +2911,11 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 
 		  /* NB: GOTPCREL relocations against local absolute
 		     symbol store relocation value in the GOT slot
-		     without relative relocation.  */
-		  if (bfd_link_pic (info)
+		     without relative relocation.  Don't generate
+		     relative relocation here if it has been generated
+		     by DT_RELR.  */
+		  if (!info->enable_dt_relr
+		      && bfd_link_pic (info)
 		      && !(sym->st_shndx == SHN_ABS
 			   && (r_type == R_X86_64_GOTPCREL
 			       || r_type == R_X86_64_GOTPCRELX
@@ -3215,6 +3230,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 	    {
 	      Elf_Internal_Rela outrel;
 	      bool skip, relocate;
+	      bool generate_dynamic_reloc = true;
 	      asection *sreloc;
 	      const char *relative_reloc_name = NULL;
 
@@ -3253,9 +3269,17 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 			  && htab->params->no_reloc_overflow_check))
 		    {
 		      relocate = true;
-		      outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE);
-		      outrel.r_addend = relocation + rel->r_addend;
-		      relative_reloc_name = "R_X86_64_RELATIVE";
+		      /* NB: Don't generate relative relocation here if
+			 it has been generated by DT_RELR.  */
+		      if (info->enable_dt_relr)
+			generate_dynamic_reloc = false;
+		      else
+			{
+			  outrel.r_info =
+			    htab->r_info (0, R_X86_64_RELATIVE);
+			  outrel.r_addend = relocation + rel->r_addend;
+			  relative_reloc_name = "R_X86_64_RELATIVE";
+			}
 		    }
 		  else if (r_type == R_X86_64_64
 			   && !ABI_64_P (output_bfd))
@@ -3323,21 +3347,24 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 		    }
 		}
 
-	      sreloc = elf_section_data (input_section)->sreloc;
-
-	      if (sreloc == NULL || sreloc->contents == NULL)
+	      if (generate_dynamic_reloc)
 		{
-		  r = bfd_reloc_notsupported;
-		  goto check_relocation_error;
-		}
+		  sreloc = elf_section_data (input_section)->sreloc;
 
-	      if (relative_reloc_name
-		  && htab->params->report_relative_reloc)
-		_bfd_x86_elf_link_report_relative_reloc
-		  (info, input_section, h, sym, relative_reloc_name,
-		   &outrel);
+		  if (sreloc == NULL || sreloc->contents == NULL)
+		    {
+		      r = bfd_reloc_notsupported;
+		      goto check_relocation_error;
+		    }
 
-	      elf_append_rela (output_bfd, sreloc, &outrel);
+		  if (relative_reloc_name
+		      && htab->params->report_relative_reloc)
+		    _bfd_x86_elf_link_report_relative_reloc
+		      (info, input_section, h, sym,
+		       relative_reloc_name, &outrel);
+
+		  elf_append_rela (output_bfd, sreloc, &outrel);
+		}
 
 	      /* If this reloc is against an external symbol, we do
 		 not want to fiddle with the addend.  Otherwise, we
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 25f7717ea88..0f4e6542ef0 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -726,6 +726,10 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd)
       ret->got_entry_size = 8;
       ret->pcrel_plt = true;
       ret->tls_get_addr = "__tls_get_addr";
+      ret->relative_r_type = R_X86_64_RELATIVE;
+      ret->relative_r_name = "R_X86_64_RELATIVE";
+      ret->elf_append_reloc = elf_append_rela;
+      ret->elf_write_addend_in_got = _bfd_elf64_write_addend;
     }
   if (ABI_64_P (abfd))
     {
@@ -733,6 +737,7 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd)
       ret->pointer_r_type = R_X86_64_64;
       ret->dynamic_interpreter = ELF64_DYNAMIC_INTERPRETER;
       ret->dynamic_interpreter_size = sizeof ELF64_DYNAMIC_INTERPRETER;
+      ret->elf_write_addend = _bfd_elf64_write_addend;
     }
   else
     {
@@ -743,6 +748,7 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd)
 	  ret->dynamic_interpreter = ELFX32_DYNAMIC_INTERPRETER;
 	  ret->dynamic_interpreter_size
 	    = sizeof ELFX32_DYNAMIC_INTERPRETER;
+	  ret->elf_write_addend = _bfd_elf32_write_addend;
 	}
       else
 	{
@@ -751,6 +757,11 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd)
 	  ret->got_entry_size = 4;
 	  ret->pcrel_plt = false;
 	  ret->pointer_r_type = R_386_32;
+	  ret->relative_r_type = R_386_RELATIVE;
+	  ret->relative_r_name = "R_386_RELATIVE";
+	  ret->elf_append_reloc = elf_append_rel;
+	  ret->elf_write_addend = _bfd_elf32_write_addend;
+	  ret->elf_write_addend_in_got = _bfd_elf32_write_addend;
 	  ret->dynamic_interpreter = ELF32_DYNAMIC_INTERPRETER;
 	  ret->dynamic_interpreter_size
 	    = sizeof ELF32_DYNAMIC_INTERPRETER;
@@ -977,6 +988,902 @@ _bfd_x86_elf_check_relocs (bfd *abfd,
   return true;
 }
 
+/* Add an entry to the relative reloc record.  */
+
+static bool
+elf_x86_relative_reloc_record_add
+  (struct bfd_link_info *info,
+   struct elf_x86_relative_reloc_data *relative_reloc,
+   Elf_Internal_Rela *rel, asection *sec,
+   asection *sym_sec, struct elf_link_hash_entry *h,
+   Elf_Internal_Sym *sym, bfd_vma offset)
+{
+  bfd_size_type newidx;
+
+  if (relative_reloc->data == NULL)
+    {
+      relative_reloc->data = bfd_malloc
+	(sizeof (struct elf_x86_relative_reloc_record));
+      relative_reloc->count = 0;
+      relative_reloc->size = 1;
+    }
+
+  newidx = relative_reloc->count++;
+
+  if (relative_reloc->count > relative_reloc->size)
+    {
+      relative_reloc->size <<= 1;
+      relative_reloc->data = bfd_realloc
+	(relative_reloc->data,
+	 (relative_reloc->size
+	  * sizeof (struct elf_x86_relative_reloc_record)));
+    }
+
+  if (relative_reloc->data == NULL)
+    {
+      info->callbacks->einfo
+	/* xgettext:c-format */
+	(_("%F%P: %pB: failed to allocate relative reloc record\n"),
+	 info->output_bfd);
+      return false;
+    }
+
+  relative_reloc->data[newidx].rel = *rel;
+  relative_reloc->data[newidx].sec = sec;
+  if (h != NULL)
+    {
+      /* Set SYM to NULL to indicate a global symbol.  */
+      relative_reloc->data[newidx].sym = NULL;
+      relative_reloc->data[newidx].u.h = h;
+    }
+  else
+    {
+      relative_reloc->data[newidx].sym = sym;
+      relative_reloc->data[newidx].u.sym_sec = sym_sec;
+    }
+  relative_reloc->data[newidx].offset = offset;
+  relative_reloc->data[newidx].address = 0;
+  return true;
+}
+
+/* After input sections have been mapped to output sections and
+   addresses of output sections are set initiallly, scan input
+   relocations with the same logic in relocate_section to determine
+   if a relative relocation should be generated.  Save the relative
+   relocation candidate information for sizing the DT_RELR section
+   later after all symbols addresses can be determined.  */
+
+bool
+_bfd_x86_elf_link_relax_section (bfd *abfd ATTRIBUTE_UNUSED,
+				 asection *input_section,
+				 struct bfd_link_info *info,
+				 bool *again)
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  Elf_Internal_Rela *internal_relocs;
+  Elf_Internal_Rela *irel, *irelend;
+  Elf_Internal_Sym *isymbuf = NULL;
+  struct elf_link_hash_entry **sym_hashes;
+  const struct elf_backend_data *bed;
+  struct elf_x86_link_hash_table *htab;
+  bfd_vma *local_got_offsets;
+  bool is_x86_64;
+  bool unaligned_section;
+
+  if (bfd_link_relocatable (info))
+    return true;
+
+  /* Assume we're not going to change any sizes, and we'll only need
+     one pass.  */
+  *again = false;
+
+  bed = get_elf_backend_data (abfd);
+  htab = elf_x86_hash_table (info, bed->target_id);
+  if (htab == NULL)
+    return true;
+
+  /* Nothing to do if there are no relocations or relative relocations
+     have been packed.  */
+  if (input_section == htab->elf.srelrdyn
+      || input_section->relative_reloc_packed
+      || ((input_section->flags & (SEC_RELOC | SEC_ALLOC))
+	  != (SEC_RELOC | SEC_ALLOC))
+      || (input_section->flags & SEC_DEBUGGING) != 0
+      || input_section->reloc_count == 0)
+    return true;
+
+  /* Skip if the section isn't aligned.  */
+  unaligned_section = input_section->alignment_power == 0;
+
+  is_x86_64 = bed->target_id == X86_64_ELF_DATA;
+
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  sym_hashes = elf_sym_hashes (abfd);
+  local_got_offsets = elf_local_got_offsets (abfd);
+
+  /* Load the relocations for this section.  */
+  internal_relocs =
+    _bfd_elf_link_read_relocs (abfd, input_section, NULL,
+			       (Elf_Internal_Rela *) NULL,
+			       info->keep_memory);
+  if (internal_relocs == NULL)
+    return false;
+
+  irelend = internal_relocs + input_section->reloc_count;
+  for (irel = internal_relocs; irel < irelend; irel++)
+    {
+      unsigned int r_type;
+      unsigned int r_symndx;
+      Elf_Internal_Sym *isym;
+      struct elf_link_hash_entry *h;
+      struct elf_x86_link_hash_entry *eh;
+      bfd_vma offset;
+      bool resolved_to_zero;
+      bool need_copy_reloc_in_pie;
+      bool pc32_reloc;
+      asection *sec;
+      /* Offset must be a multiple of 2.  */
+      bool unaligned_offset = (irel->r_offset & 1) != 0;
+
+      /* Get the value of the symbol referred to by the reloc.  */
+      r_symndx = htab->r_sym (irel->r_info);
+
+      r_type = ELF32_R_TYPE (irel->r_info);
+      /* Clear the R_X86_64_converted_reloc_bit bit.  */
+      r_type &= ~R_X86_64_converted_reloc_bit;
+
+      sec = NULL;
+      h = NULL;
+
+      if (r_symndx < symtab_hdr->sh_info)
+	{
+	  /* Read this BFD's local symbols.  */
+	  if (isymbuf == NULL)
+	    {
+	      isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	      if (isymbuf == NULL)
+		isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+						symtab_hdr->sh_info, 0,
+						NULL, NULL, NULL);
+	      if (isymbuf == NULL)
+		goto error_return;
+	    }
+
+	  isym = isymbuf + r_symndx;
+	  switch (isym->st_shndx)
+	    {
+	    case SHN_ABS:
+	      sec = bfd_abs_section_ptr;
+	      break;
+	    case SHN_COMMON:
+	      sec = bfd_com_section_ptr;
+	      break;
+	    case SHN_X86_64_LCOMMON:
+	      if (!is_x86_64)
+		abort ();
+	      sec = &_bfd_elf_large_com_section;
+	      break;
+	    default:
+	      sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+	      break;
+	    }
+
+	  /* Check relocation against local STT_GNU_IFUNC symbol.  */
+	  if (ELF32_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
+	    {
+	      h = _bfd_elf_x86_get_local_sym_hash (htab, abfd, irel,
+						   true);
+	      if (h == NULL)
+		goto error_return;
+	    }
+
+	  resolved_to_zero = false;
+	}
+      else
+	{
+	  /* Get H and SEC for GENERATE_DYNAMIC_RELOCATION_P below.  */
+	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+	  while (h->root.type == bfd_link_hash_indirect
+		 || h->root.type == bfd_link_hash_warning)
+	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+	  if (h->root.type == bfd_link_hash_defined
+	      || h->root.type == bfd_link_hash_defweak)
+	    sec = h->root.u.def.section;
+
+	  isym = NULL;
+	}
+
+      eh = (struct elf_x86_link_hash_entry *) h;
+      resolved_to_zero = (eh != NULL
+			  && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh));
+
+      if (X86_GOT_TYPE_P (is_x86_64, r_type))
+	{
+	  /* Pack GOT relative relocations.  There should be only a
+	     single R_*_RELATIVE relocation in GOT.  */
+	  if (eh != NULL)
+	    {
+	      if (eh->got_relative_reloc_done)
+		continue;
+
+	      if (!(h->type != STT_GNU_IFUNC
+		    && RESOLVED_LOCALLY_P (info, h, htab)
+		    && GENERATE_RELATIVE_RELOC_P (info, h)))
+		continue;
+
+	      eh->no_finish_dynamic_symbol = 1;
+	      eh->got_relative_reloc_done = 1;
+	      offset = h->got.offset;
+	    }
+	  else
+	    {
+	      if (elf_x86_relative_reloc_done (abfd)[r_symndx])
+		continue;
+
+	      if (!X86_LOCAL_GOT_RELATIVE_RELOC_P (is_x86_64, info,
+						   isym))
+		continue;
+
+	      elf_x86_relative_reloc_done (abfd)[r_symndx] = 1;
+	      offset = local_got_offsets[r_symndx];
+	    }
+
+	  if (!elf_x86_relative_reloc_record_add (info,
+						  &htab->relative_reloc,
+						  irel, htab->elf.sgot,
+						  sec, h, isym, offset))
+	    goto error_return;
+
+	  continue;
+	}
+
+      if (is_x86_64
+	  && irel->r_addend == 0
+	  && !ABI_64_P (info->output_bfd))
+	{
+	  /* For x32, if addend is zero, treat R_X86_64_64 like
+	     R_X86_64_32 and R_X86_64_SIZE64 like R_X86_64_SIZE32.  */
+	  if (r_type == R_X86_64_64)
+	    r_type = R_X86_64_32;
+	  else if (r_type == R_X86_64_SIZE64)
+	    r_type = R_X86_64_SIZE32;
+	}
+
+      if (!X86_RELATIVE_RELOC_TYPE_P (is_x86_64, r_type)
+	  || (h != NULL && h->type == STT_GNU_IFUNC))
+	continue;
+
+      /* Pack non-GOT relative relocations.  */
+      if (is_x86_64)
+	{
+	  need_copy_reloc_in_pie =
+	    (bfd_link_pie (info)
+	     && h != NULL
+	     && (h->needs_copy
+		 || eh->needs_copy
+		 || (h->root.type == bfd_link_hash_undefined))
+	     && (X86_PCREL_TYPE_P (true, r_type)
+		 || X86_SIZE_TYPE_P (true, r_type)));
+	  pc32_reloc = false;
+	}
+      else
+	{
+	  need_copy_reloc_in_pie = false;
+	  pc32_reloc = r_type == R_386_PC32;
+	}
+
+      if (GENERATE_DYNAMIC_RELOCATION_P (is_x86_64, info, eh, r_type,
+					 sec, need_copy_reloc_in_pie,
+					 resolved_to_zero, pc32_reloc))
+	{
+	  /* When generating a shared object, these relocations
+	     are copied into the output file to be resolved at run
+	     time.	*/
+	  offset = _bfd_elf_section_offset (info->output_bfd, info,
+					    input_section,
+					    irel->r_offset);
+	  if (offset == (bfd_vma) -1
+	      || offset == (bfd_vma) -2
+	      || COPY_INPUT_RELOC_P (is_x86_64, info, h, r_type))
+	    continue;
+
+	  /* This symbol is local, or marked to become local.  When
+	     relocation overflow check is disabled, we convert
+	     R_X86_64_32 to dynamic R_X86_64_RELATIVE.  */
+	  if (is_x86_64
+	      && !(r_type == htab->pointer_r_type
+		   || (r_type == R_X86_64_32
+		       && htab->params->no_reloc_overflow_check)))
+	    continue;
+
+	  if (!elf_x86_relative_reloc_record_add
+	        (info,
+		 ((unaligned_section || unaligned_offset)
+		  ? &htab->unaligned_relative_reloc
+		  : &htab->relative_reloc),
+		 irel, input_section, sec, h, isym, offset))
+	    goto error_return;
+	}
+    }
+
+  input_section->relative_reloc_packed = 1;
+
+  return true;
+
+error_return:
+  if ((unsigned char *) isymbuf != symtab_hdr->contents)
+    free (isymbuf);
+  if (elf_section_data (input_section)->relocs != internal_relocs)
+    free (internal_relocs);
+  return false;
+}
+
+/* Add an entry to the 64-bit DT_RELR bitmap.  */
+
+static void
+elf64_dt_relr_bitmap_add
+  (struct bfd_link_info *info, struct elf_dt_relr_bitmap *bitmap,
+   uint64_t entry)
+{
+  bfd_size_type newidx;
+
+  if (bitmap->u.elf64 == NULL)
+    {
+      bitmap->u.elf64 = bfd_malloc (sizeof (uint64_t));
+      bitmap->count = 0;
+      bitmap->size = 1;
+    }
+
+  newidx = bitmap->count++;
+
+  if (bitmap->count > bitmap->size)
+    {
+      bitmap->size <<= 1;
+      bitmap->u.elf64 = bfd_realloc (bitmap->u.elf64,
+				     (bitmap->size * sizeof (uint64_t)));
+    }
+
+  if (bitmap->u.elf64 == NULL)
+    {
+      info->callbacks->einfo
+	/* xgettext:c-format */
+	(_("%F%P: %pB: failed to allocate 64-bit DT_RELR bitmap\n"),
+	 info->output_bfd);
+    }
+
+  bitmap->u.elf64[newidx] = entry;
+}
+
+/* Add an entry to the 32-bit DT_RELR bitmap.  */
+
+static void
+elf32_dt_relr_bitmap_add
+  (struct bfd_link_info *info, struct elf_dt_relr_bitmap *bitmap,
+   uint32_t entry)
+{
+  bfd_size_type newidx;
+
+  if (bitmap->u.elf32 == NULL)
+    {
+      bitmap->u.elf32 = bfd_malloc (sizeof (uint32_t));
+      bitmap->count = 0;
+      bitmap->size = 1;
+    }
+
+  newidx = bitmap->count++;
+
+  if (bitmap->count > bitmap->size)
+    {
+      bitmap->size <<= 1;
+      bitmap->u.elf32 = bfd_realloc (bitmap->u.elf32,
+				     (bitmap->size * sizeof (uint32_t)));
+    }
+
+  if (bitmap->u.elf32 == NULL)
+    {
+      info->callbacks->einfo
+	/* xgettext:c-format */
+	(_("%F%P: %pB: failed to allocate 32-bit DT_RELR bitmap\n"),
+	 info->output_bfd);
+    }
+
+  bitmap->u.elf32[newidx] = entry;
+}
+
+void
+_bfd_elf32_write_addend (bfd *abfd, uint64_t value, void *addr)
+{
+  bfd_put_32 (abfd, value, addr);
+}
+
+void
+_bfd_elf64_write_addend (bfd *abfd, uint64_t value, void *addr)
+{
+  bfd_put_64 (abfd, value, addr);
+}
+
+/* Size or finish relative relocations to determine the run-time
+   addresses for DT_RELR bitmap computation later.  OUTREL is set
+   to NULL in the sizing phase and non-NULL in the finising phase
+   where the regular relative relocations will be written out.  */
+
+static void
+elf_x86_size_or_finish_relative_reloc
+  (bool is_x86_64, struct bfd_link_info *info,
+   struct elf_x86_link_hash_table *htab, bool unaligned,
+   Elf_Internal_Rela *outrel)
+{
+  unsigned int align_mask;
+  bfd_size_type i, count;
+  asection *sec, *srel;
+  struct elf_link_hash_entry *h;
+  bfd_vma offset;
+  Elf_Internal_Sym *sym;
+  asection *sym_sec;
+  asection *sgot = htab->elf.sgot;
+  asection *srelgot = htab->elf.srelgot;
+  struct elf_x86_relative_reloc_data *relative_reloc;
+
+  if (unaligned)
+    {
+      align_mask = 0;
+      relative_reloc = &htab->unaligned_relative_reloc;
+    }
+  else
+    {
+      align_mask = 1;
+      relative_reloc = &htab->relative_reloc;
+    }
+
+  count = relative_reloc->count;
+  for (i = 0; i < count; i++)
+    {
+      sec = relative_reloc->data[i].sec;
+      sym = relative_reloc->data[i].sym;
+
+      /* If SYM is NULL, it must be a global symbol.  */
+      if (sym == NULL)
+	h = relative_reloc->data[i].u.h;
+      else
+	h = NULL;
+
+      if (is_x86_64)
+	{
+	  bfd_vma relocation;
+	  /* This function may be called more than once and REL may be
+	     updated by _bfd_elf_rela_local_sym below.  */
+	  Elf_Internal_Rela rel = relative_reloc->data[i].rel;
+
+	  if (h != NULL)
+	    {
+	      if (h->root.type == bfd_link_hash_defined
+		  || h->root.type == bfd_link_hash_defweak)
+		{
+		  sym_sec = h->root.u.def.section;
+		  relocation = (h->root.u.def.value
+				+ sym_sec->output_section->vma
+				+ sym_sec->output_offset);
+		}
+	      else
+		{
+		  /* Allow undefined symbol only at the sizing phase.  */
+		  if (outrel == NULL)
+		    relocation = 0;
+		  else
+		    abort ();
+		}
+	    }
+	  else
+	    {
+	      sym_sec = relative_reloc->data[i].u.sym_sec;
+	      relocation = _bfd_elf_rela_local_sym
+		(info->output_bfd, sym, &sym_sec, &rel);
+	    }
+
+	  if (outrel != NULL)
+	    {
+	      outrel->r_addend = relocation;
+	      if (sec == sgot)
+		{
+		  if (h != NULL && h->needs_plt)
+		    abort ();
+		}
+	      else
+		outrel->r_addend += rel.r_addend;
+
+	      /* Write the implicit addend if ALIGN_MASK isn't 0.  */
+	      if (align_mask)
+		{
+		  if (sec == sgot)
+		    {
+		      if (relative_reloc->data[i].offset >= sec->size)
+			abort ();
+		      htab->elf_write_addend_in_got
+			(info->output_bfd, outrel->r_addend,
+			 sec->contents + relative_reloc->data[i].offset);
+		    }
+		  else
+		    {
+		      if (rel.r_offset >= sec->size)
+			abort ();
+		      htab->elf_write_addend
+			(info->output_bfd, outrel->r_addend,
+			 (elf_section_data (sec)->this_hdr.contents
+			  + rel.r_offset));
+		    }
+		}
+	    }
+	}
+
+      if (sec == sgot)
+	srel = srelgot;
+      else
+	srel = elf_section_data (sec)->sreloc;
+      offset = (sec->output_section->vma + sec->output_offset
+		+ relative_reloc->data[i].offset);
+      relative_reloc->data[i].address = offset;
+      if (outrel != NULL)
+	{
+	  outrel->r_offset = offset;
+
+	  if ((outrel->r_offset & align_mask) != 0)
+	    abort ();
+
+	  if (htab->params->report_relative_reloc)
+	    _bfd_x86_elf_link_report_relative_reloc
+	      (info, sec, h, sym, htab->relative_r_name, outrel);
+
+	  /* Generate regular relative relocation if ALIGN_MASK is 0.  */
+	  if (align_mask == 0)
+	    htab->elf_append_reloc (info->output_bfd, srel, outrel);
+	}
+    }
+}
+
+/* Compute the DT_RELR section size.  Set NEED_PLAYOUT to true if
+   the DT_RELR section size has been increased.  */
+
+static void
+elf_x86_compute_dl_relr_bitmap
+  (struct bfd_link_info *info, struct elf_x86_link_hash_table *htab,
+   bool *need_layout)
+{
+  bfd_vma base;
+  bfd_size_type i, count, new_count;
+  struct elf_x86_relative_reloc_data *relative_reloc =
+    &htab->relative_reloc;
+  /* Save the old DT_RELR bitmap count.  Don't shrink the DT_RELR bitmap
+     if the new DT_RELR bitmap count is smaller than the old one.  Pad
+     with trailing 1s which won't be decoded to more relocations.  */
+  bfd_size_type dt_relr_bitmap_count = htab->dt_relr_bitmap.count;
+
+  /* Clear the DT_RELR bitmap count.  */
+  htab->dt_relr_bitmap.count = 0;
+
+  count = relative_reloc->count;
+
+  if (ABI_64_P (info->output_bfd))
+    {
+      /* Compute the 64-bit DT_RELR bitmap.  */
+      i = 0;
+      while (i < count)
+	{
+	  if ((relative_reloc->data[i].address % 1) != 0)
+	    abort ();
+
+	  elf64_dt_relr_bitmap_add (info, &htab->dt_relr_bitmap,
+				    relative_reloc->data[i].address);
+
+	  base = relative_reloc->data[i].address + 8;
+	  i++;
+
+	  while (i < count)
+	    {
+	      uint64_t bitmap = 0;
+	      for (; i < count; i++)
+		{
+		  bfd_vma delta = (relative_reloc->data[i].address
+				   - base);
+		  /* Stop if it is too far from base.  */
+		  if (delta >= 63 * 8)
+		    break;
+		  /* Stop if it isn't a multiple of 8.  */
+		  if ((delta % 8) != 0)
+		    break;
+		  bitmap |= 1ULL << (delta / 8);
+		}
+
+	      if (bitmap == 0)
+		break;
+
+	      elf64_dt_relr_bitmap_add (info, &htab->dt_relr_bitmap,
+					(bitmap << 1) | 1);
+
+	      base += 63 * 8;
+	    }
+	}
+
+      new_count = htab->dt_relr_bitmap.count;
+      if (dt_relr_bitmap_count > new_count)
+	{
+	  /* Don't shrink the DT_RELR section size to avoid section
+	     layout oscillation.  Instead, pad the DT_RELR bitmap with
+	     1s which do not decode to more relocations.  */
+
+	  htab->dt_relr_bitmap.count = dt_relr_bitmap_count;
+	  count = dt_relr_bitmap_count - new_count;
+	  for (i = 0; i < count; i++)
+	    htab->dt_relr_bitmap.u.elf64[new_count + i] = 1;
+	}
+    }
+  else
+    {
+      /* Compute the 32-bit DT_RELR bitmap.  */
+      i = 0;
+      while (i < count)
+	{
+	  if ((relative_reloc->data[i].address % 1) != 0)
+	    abort ();
+
+	  elf32_dt_relr_bitmap_add (info, &htab->dt_relr_bitmap,
+				    relative_reloc->data[i].address);
+
+	  base = relative_reloc->data[i].address + 4;
+	  i++;
+
+	  while (i < count)
+	    {
+	      uint32_t bitmap = 0;
+	      for (; i < count; i++)
+		{
+		  bfd_vma delta = (relative_reloc->data[i].address
+				   - base);
+		  /* Stop if it is too far from base.  */
+		  if (delta >= 31 * 4)
+		    break;
+		  /* Stop if it isn't a multiple of 4.  */
+		  if ((delta % 4) != 0)
+		    break;
+		  bitmap |= 1ULL << (delta / 4);
+		}
+
+	      if (bitmap == 0)
+		break;
+
+	      elf32_dt_relr_bitmap_add (info, &htab->dt_relr_bitmap,
+					(bitmap << 1) | 1);
+
+	      base += 31 * 4;
+	    }
+	}
+
+      new_count = htab->dt_relr_bitmap.count;
+      if (dt_relr_bitmap_count > new_count)
+	{
+	  /* Don't shrink the DT_RELR section size to avoid section
+	     layout oscillation.  Instead, pad the DT_RELR bitmap with
+	     1s which do not decode to more relocations.  */
+
+	  htab->dt_relr_bitmap.count = dt_relr_bitmap_count;
+	  count = dt_relr_bitmap_count - new_count;
+	  for (i = 0; i < count; i++)
+	    htab->dt_relr_bitmap.u.elf32[new_count + i] = 1;
+	}
+    }
+
+  if (htab->dt_relr_bitmap.count != dt_relr_bitmap_count)
+    {
+      if (need_layout)
+	{
+	  /* The .relr.dyn section size is changed.  Update the section
+	     size and tell linker to layout sections again.  */
+	  htab->elf.srelrdyn->size =
+	    (htab->dt_relr_bitmap.count
+	     * (ABI_64_P (info->output_bfd) ? 8 : 4));
+
+	  *need_layout = true;
+	}
+      else
+	info->callbacks->einfo
+	  /* xgettext:c-format */
+	  (_("%F%P: %pB: size of compact relative reloc section is "
+	     "changed: new (%lu) != old (%lu)\n"),
+	   info->output_bfd, htab->dt_relr_bitmap.count,
+	   dt_relr_bitmap_count);
+    }
+}
+
+/* Write out the DT_RELR section.  */
+
+static void
+elf_x86_write_dl_relr_bitmap (struct bfd_link_info *info,
+			      struct elf_x86_link_hash_table *htab)
+{
+  asection *sec = htab->elf.srelrdyn;
+  bfd_size_type size = sec->size;
+  bfd_size_type i;
+  unsigned char *contents;
+
+  contents = (unsigned char *) bfd_alloc (sec->owner, size);
+  if (contents == NULL)
+    info->callbacks->einfo
+      /* xgettext:c-format */
+      (_("%F%P: %pB: failed to allocate compact relative reloc section\n"),
+       info->output_bfd);
+
+  /* Cache the section contents for elf_link_input_bfd.  */
+  sec->contents = contents;
+
+  if (ABI_64_P (info->output_bfd))
+    for (i = 0; i < htab->dt_relr_bitmap.count; i++, contents += 8)
+      bfd_put_64 (info->output_bfd, htab->dt_relr_bitmap.u.elf64[i],
+		  contents);
+  else
+    for (i = 0; i < htab->dt_relr_bitmap.count; i++, contents += 4)
+      bfd_put_32 (info->output_bfd, htab->dt_relr_bitmap.u.elf32[i],
+		  contents);
+}
+
+/* Sort relative relocations by address.  */
+
+static int
+elf_x86_relative_reloc_compare (const void *pa, const void *pb)
+{
+  struct elf_x86_relative_reloc_record *a =
+    (struct elf_x86_relative_reloc_record *) pa;
+  struct elf_x86_relative_reloc_record *b =
+    (struct elf_x86_relative_reloc_record *) pb;
+  if (a->address < b->address)
+    return -1;
+  if (a->address > b->address)
+    return 1;
+  return 0;
+}
+
+bool
+_bfd_elf_x86_size_relative_relocs (struct bfd_link_info *info,
+				   bool *need_layout)
+{
+  struct elf_x86_link_hash_table *htab;
+  const struct elf_backend_data *bed;
+  bool is_x86_64;
+  bfd_size_type i, count, unaligned_count;
+  asection *sec, *srel;
+
+  /* Do nothing for ld -r.  */
+  if (bfd_link_relocatable (info))
+    return true;
+
+  bed = get_elf_backend_data (info->output_bfd);
+  htab = elf_x86_hash_table (info, bed->target_id);
+  if (htab == NULL)
+    return false;
+
+  count = htab->relative_reloc.count;
+  unaligned_count = htab->unaligned_relative_reloc.count;
+  if (count == 0)
+    {
+      if (htab->generate_relative_reloc_pass == 0
+	  && htab->elf.srelrdyn != NULL)
+	{
+	  /* Remove the empty .relr.dyn sections now.  */
+	  if (!bfd_is_abs_section (htab->elf.srelrdyn->output_section))
+	    {
+	      bfd_section_list_remove
+		(info->output_bfd, htab->elf.srelrdyn->output_section);
+	      info->output_bfd->section_count--;
+	    }
+	  bfd_section_list_remove (htab->elf.srelrdyn->owner,
+				   htab->elf.srelrdyn);
+	  htab->elf.srelrdyn->owner->section_count--;
+	}
+      if (unaligned_count == 0)
+	{
+	  htab->generate_relative_reloc_pass++;
+	  return true;
+	}
+    }
+
+  is_x86_64 = bed->target_id == X86_64_ELF_DATA;
+
+  /* Size relative relocations.  */
+  if (htab->generate_relative_reloc_pass)
+    {
+      /* Reset the regular relative relocation count.  */
+      for (i = 0; i < unaligned_count; i++)
+	{
+	  sec = htab->unaligned_relative_reloc.data[i].sec;
+	  srel = elf_section_data (sec)->sreloc;
+	  srel->reloc_count = 0;
+	}
+    }
+  else
+    {
+      /* Remove the reserved space for compact relative relocations.  */
+      if (count)
+	{
+	  asection *sgot = htab->elf.sgot;
+	  asection *srelgot = htab->elf.srelgot;
+
+	  for (i = 0; i < count; i++)
+	    {
+	      sec = htab->relative_reloc.data[i].sec;
+	      if (sec == sgot)
+		srel = srelgot;
+	      else
+		srel = elf_section_data (sec)->sreloc;
+	      srel->size -= htab->sizeof_reloc;
+	    }
+	}
+    }
+
+  /* Size unaligned relative relocations.  */
+  if (unaligned_count)
+    elf_x86_size_or_finish_relative_reloc (is_x86_64, info, htab,
+					   true, NULL);
+
+  if (count)
+    {
+      elf_x86_size_or_finish_relative_reloc (is_x86_64, info, htab,
+					     false, NULL);
+
+      /* Sort relative relocations by addresses.  We only need to
+	 sort them in the first pass since the relative positions
+	 won't change.  */
+      if (htab->generate_relative_reloc_pass == 0)
+	qsort (htab->relative_reloc.data, count,
+	       sizeof (struct elf_x86_relative_reloc_record),
+	       elf_x86_relative_reloc_compare);
+
+      elf_x86_compute_dl_relr_bitmap (info, htab, need_layout);
+    }
+
+  htab->generate_relative_reloc_pass++;
+
+  return true;
+}
+
+bool
+_bfd_elf_x86_finish_relative_relocs (struct bfd_link_info *info)
+{
+  struct elf_x86_link_hash_table *htab;
+  const struct elf_backend_data *bed;
+  Elf_Internal_Rela outrel;
+  bool is_x86_64;
+  bfd_size_type count;
+
+  /* Do nothing for ld -r.  */
+  if (bfd_link_relocatable (info))
+    return true;
+
+  bed = get_elf_backend_data (info->output_bfd);
+  htab = elf_x86_hash_table (info, bed->target_id);
+  if (htab == NULL)
+    return false;
+
+  is_x86_64 = bed->target_id == X86_64_ELF_DATA;
+
+  outrel.r_info = htab->r_info (0, htab->relative_r_type);
+
+  if (htab->unaligned_relative_reloc.count)
+    elf_x86_size_or_finish_relative_reloc (is_x86_64, info, htab,
+					   true, &outrel);
+
+  count = htab->relative_reloc.count;
+  if (count)
+    {
+      elf_x86_size_or_finish_relative_reloc (is_x86_64, info, htab,
+					     false, &outrel);
+
+      elf_x86_compute_dl_relr_bitmap (info, htab, NULL);
+
+      elf_x86_write_dl_relr_bitmap (info, htab);
+    }
+
+  return true;
+}
+
 bool
 _bfd_elf_x86_valid_reloc_p (asection *input_section,
 			    struct bfd_link_info *info,
@@ -1332,6 +2239,11 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
       if ((s->flags & SEC_LINKER_CREATED) == 0)
 	continue;
 
+      /* The .relr.dyn section for compact relative relocation will
+	 be filled later.  */
+      if (s == htab->elf.srelrdyn)
+	continue;
+
       if (s == htab->elf.splt
 	  || s == htab->elf.sgot)
 	{
@@ -1459,6 +2371,7 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
   asection *sdyn;
   bfd_byte *dyncon, *dynconend;
   bfd_size_type sizeof_dyn;
+  bfd_size_type dt_relr_bitmap_count;
 
   bed = get_elf_backend_data (output_bfd);
   htab = elf_x86_hash_table (info, bed->target_id);
@@ -1517,6 +2430,8 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
   if (sdyn == NULL || htab->elf.sgot == NULL)
     abort ();
 
+  dt_relr_bitmap_count = htab->dt_relr_bitmap.count;
+
   sizeof_dyn = bed->s->sizeof_dyn;
   dyncon = sdyn->contents;
   dynconend = sdyn->contents + sdyn->size;
@@ -1535,6 +2450,28 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
 	    break;
 	  continue;
 
+	case DT_NULL:
+	  if (dt_relr_bitmap_count != 0)
+	    {
+	      /* Convert 3 spare dynamic tags to DT_RELR, DT_RELRSZ and
+		 DT_RELRENT for compact relative relocation.  */
+	      s = htab->elf.srelrdyn;
+	      dyn.d_tag = DT_RELR;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
+	      (*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon);
+	      dyncon += sizeof_dyn;
+	      dyn.d_tag = DT_RELRSZ;
+	      dyn.d_un.d_val = s->size;
+	      (*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon);
+	      dyncon += sizeof_dyn;
+	      dyn.d_tag = DT_RELRENT;
+	      dyn.d_un.d_val = ABI_64_P (output_bfd) ? 8 : 4;
+	      elf_section_data (s->output_section)->this_hdr.sh_entsize
+		= dyn.d_un.d_val;
+	      dt_relr_bitmap_count = 0;
+	    }
+	  break;
+
 	case DT_PLTGOT:
 	  s = htab->elf.sgotplt;
 	  dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index 1bb80280918..4b5784ca08a 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -47,18 +47,35 @@
 #define X86_SIZE_TYPE_P(IS_X86_64, TYPE) \
   ((IS_X86_64) ? X86_64_SIZE_TYPE_P(TYPE) : I386_SIZE_TYPE_P (TYPE))
 
-#define X86_64_NEED_DYNAMIC_RELOC_TYPE_P(TYPE) \
-  (X86_64_SIZE_TYPE_P (TYPE) \
-   || X86_64_PCREL_TYPE_P (TYPE) \
+#define X86_64_GOT_TYPE_P(TYPE) \
+  ((TYPE) == R_X86_64_GOTPCREL \
+   || (TYPE) == R_X86_64_GOTPCRELX \
+   || (TYPE) == R_X86_64_REX_GOTPCRELX)
+#define I386_GOT_TYPE_P(TYPE) \
+  ((TYPE) == R_386_GOT32 || (TYPE) == R_386_GOT32X)
+#define X86_GOT_TYPE_P(IS_X86_64, TYPE) \
+  ((IS_X86_64) ? X86_64_GOT_TYPE_P (TYPE) : I386_GOT_TYPE_P (TYPE))
+
+#define X86_64_RELATIVE_RELOC_TYPE_P(TYPE) \
+  (X86_64_PCREL_TYPE_P (TYPE) \
    || (TYPE) == R_X86_64_8 \
    || (TYPE) == R_X86_64_16 \
    || (TYPE) == R_X86_64_32 \
    || (TYPE) == R_X86_64_32S \
    || (TYPE) == R_X86_64_64)
+#define I386_RELATIVE_RELOC_TYPE_P(TYPE) \
+  ((TYPE) == R_386_32 || (TYPE) == R_386_PC32)
+#define X86_RELATIVE_RELOC_TYPE_P(IS_X86_64, TYPE) \
+  ((IS_X86_64) \
+   ? X86_64_RELATIVE_RELOC_TYPE_P (TYPE) \
+   : I386_RELATIVE_RELOC_TYPE_P(TYPE))
+
+#define X86_64_NEED_DYNAMIC_RELOC_TYPE_P(TYPE) \
+  (X86_64_SIZE_TYPE_P (TYPE) \
+   || X86_64_RELATIVE_RELOC_TYPE_P (TYPE))
 #define I386_NEED_DYNAMIC_RELOC_TYPE_P(TYPE) \
   (I386_SIZE_TYPE_P (TYPE) \
-   || I386_PCREL_TYPE_P (TYPE) \
-   || (TYPE) == R_386_32 \
+   || I386_RELATIVE_RELOC_TYPE_P (TYPE) \
    || (TYPE) == R_386_TLS_LE \
    || (TYPE) == R_386_TLS_LE_32)
 #define X86_NEED_DYNAMIC_RELOC_TYPE_P(IS_X86_64, TYPE) \
@@ -66,11 +83,23 @@
    ? X86_64_NEED_DYNAMIC_RELOC_TYPE_P (TYPE) \
    : I386_NEED_DYNAMIC_RELOC_TYPE_P (TYPE))
 
+#define X86_LOCAL_GOT_RELATIVE_RELOC_P(IS_X86_64, INFO, SYM) \
+  (bfd_link_pic (INFO) \
+   && (!(IS_X86_64) || ((SYM) != NULL && (SYM)->st_shndx != SHN_ABS)))
+
 #define PLT_CIE_LENGTH		20
 #define PLT_FDE_LENGTH		36
 #define PLT_FDE_START_OFFSET	4 + PLT_CIE_LENGTH + 8
 #define PLT_FDE_LEN_OFFSET	4 + PLT_CIE_LENGTH + 12
 
+#define I386_PCREL_TYPE_P(TYPE) ((TYPE) == R_386_PC32)
+#define X86_64_PCREL_TYPE_P(TYPE) \
+  ((TYPE) == R_X86_64_PC8 \
+   || (TYPE) == R_X86_64_PC16 \
+   || (TYPE) == R_X86_64_PC32 \
+   || (TYPE) == R_X86_64_PC32_BND \
+   || (TYPE) == R_X86_64_PC64)
+
 #define ABI_64_P(abfd) \
   (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64)
 
@@ -160,12 +189,18 @@
    relocations against resolved undefined weak symbols in PIE, except
    when PC32_RELOC is TRUE.  Undefined weak symbol is bound locally
    when PIC is false.  Don't generate dynamic relocations against
-   non-preemptible absolute symbol.  */
+   non-preemptible absolute symbol.  NB: rel_from_abs is set on symbols
+   defined by linker scripts from "dot" (also SEGMENT_START or ORIGIN)
+   outside of an output section statement, which will be converted from
+   absolute to section-relative in set_sym_sections called from
+   ldexp_finalize_syms after ldemul_finish.   */
 #define GENERATE_DYNAMIC_RELOCATION_P(IS_X86_64, 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 \
+	     || (EH)->elf.root.rel_from_abs == 0) \
 	 && ((EH) == NULL \
 	     || SYMBOL_REFERENCES_LOCAL (INFO, &(EH)->elf))) \
     && !(NEED_COPY_RELOC_IN_PIE) \
@@ -302,6 +337,10 @@ struct elf_x86_link_hash_entry
   /* Don't call finish_dynamic_symbol on this symbol.  */
   unsigned int no_finish_dynamic_symbol : 1;
 
+  /* R_*_RELATIVE relocation in GOT for this symbol has been
+     processed.  */
+  unsigned int got_relative_reloc_done : 1;
+
   /* TRUE if symbol is __tls_get_addr.  */
   unsigned int tls_get_addr : 1;
 
@@ -481,6 +520,52 @@ struct elf_x86_plt_layout
 #define elf_x86_hash_entry(ent) \
   ((struct elf_x86_link_hash_entry *)(ent))
 
+/* Information of an input relocation used to compute its contribution
+   to the DT_RELR section size.  */
+
+struct elf_x86_relative_reloc_record
+{
+  /* The original relocation info.  */
+  Elf_Internal_Rela rel;
+  /* The input or the GOT section where the relocation is applied.  */
+  asection *sec;
+  /* Local symbol info.  NULL for global symbol.  */
+  Elf_Internal_Sym *sym;
+  union
+    {
+      /* Section where the local symbol is defined.  */
+      asection *sym_sec;
+      /* Global symbol hash.  */
+      struct elf_link_hash_entry *h;
+    } u;
+  /* The offset into the output section where the relative relocation
+     will be applied at run-time.  */
+  bfd_vma offset;
+  /* The run-time address.  */
+  bfd_vma address;
+};
+
+struct elf_x86_relative_reloc_data
+{
+  bfd_size_type count;
+  bfd_size_type size;
+  struct elf_x86_relative_reloc_record *data;
+};
+
+/* DT_RELR bitmap.  */
+struct elf_dt_relr_bitmap
+{
+  bfd_size_type count;
+  bfd_size_type size;
+  union
+    {
+      /* 32-bit bitmap.  */
+      uint32_t *elf32;
+      /* 64-bit bitmap.  */
+      uint64_t *elf64;
+    } u;
+};
+
 /* x86 ELF linker hash table.  */
 
 struct elf_x86_link_hash_table
@@ -533,6 +618,18 @@ struct elf_x86_link_hash_table
      is only used for i386.  */
   bfd_vma next_tls_desc_index;
 
+  /* DT_RELR bitmap.  */
+  struct elf_dt_relr_bitmap dt_relr_bitmap;
+
+  /* Relative relocation data.  */
+  struct elf_x86_relative_reloc_data relative_reloc;
+
+  /* Unaligned relative relocation data.  */
+  struct elf_x86_relative_reloc_data unaligned_relative_reloc;
+
+  /* Number of relative reloc generation pass.  */
+  unsigned int generate_relative_reloc_pass;
+
    /* Value used to fill the unused bytes of the first PLT entry.  This
       is only used for i386.  */
   bfd_byte plt0_pad_byte;
@@ -554,9 +651,14 @@ struct elf_x86_link_hash_table
   unsigned int sizeof_reloc;
   unsigned int got_entry_size;
   unsigned int pointer_r_type;
+  unsigned int relative_r_type;
   int dynamic_interpreter_size;
   const char *dynamic_interpreter;
   const char *tls_get_addr;
+  const char *relative_r_name;
+  void (*elf_append_reloc) (bfd *, asection *, Elf_Internal_Rela *);
+  void (*elf_write_addend) (bfd *, uint64_t, void *);
+  void (*elf_write_addend_in_got) (bfd *, uint64_t, void *);
 
   /* Options passed from the linker.  */
   struct elf_linker_x86_params *params;
@@ -591,6 +693,10 @@ struct elf_x86_obj_tdata
 
   /* GOTPLT entries for TLS descriptors.  */
   bfd_vma *local_tlsdesc_gotent;
+
+  /* R_*_RELATIVE relocation in GOT for this local symbol has been
+     processed.  */
+  char *relative_reloc_done;
 };
 
 enum elf_x86_plt_type
@@ -626,6 +732,9 @@ struct elf_x86_plt
 #define elf_x86_local_tlsdesc_gotent(abfd) \
   (elf_x86_tdata (abfd)->local_tlsdesc_gotent)
 
+#define elf_x86_relative_reloc_done(abfd) \
+  (elf_x86_tdata (abfd)->relative_reloc_done)
+
 #define elf_x86_compute_jump_table_size(htab) \
   ((htab)->elf.srelplt->reloc_count * (htab)->got_entry_size)
 
@@ -637,6 +746,7 @@ struct elf_x86_plt
 /* Rename some of the generic section flags to better document how they
    are used here.  */
 #define check_relocs_failed	sec_flg0
+#define relative_reloc_packed	sec_flg1
 
 extern bool _bfd_x86_elf_mkobject
   (bfd *);
@@ -676,6 +786,18 @@ extern bool _bfd_x86_elf_check_relocs
   (bfd *, struct bfd_link_info *, asection *,
    const Elf_Internal_Rela *);
 
+extern bool _bfd_x86_elf_link_relax_section
+  (bfd *, asection *, struct bfd_link_info *, bool *);
+
+extern bool _bfd_elf_x86_size_relative_relocs
+  (struct bfd_link_info *, bool *);
+
+extern bool _bfd_elf_x86_finish_relative_relocs
+  (struct bfd_link_info *);
+
+extern void _bfd_elf32_write_addend (bfd *, uint64_t, void *);
+extern void _bfd_elf64_write_addend (bfd *, uint64_t, void *);
+
 extern bool _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 *,
@@ -752,6 +874,10 @@ extern void _bfd_x86_elf_link_report_relative_reloc
   _bfd_x86_elf_link_check_relocs
 #define bfd_elf32_bfd_link_check_relocs \
   _bfd_x86_elf_link_check_relocs
+#define bfd_elf32_bfd_relax_section \
+  _bfd_x86_elf_link_relax_section
+#define bfd_elf64_bfd_relax_section \
+  _bfd_x86_elf_link_relax_section
 
 #define elf_backend_check_relocs \
   _bfd_x86_elf_check_relocs
@@ -777,6 +903,10 @@ extern void _bfd_x86_elf_link_report_relative_reloc
   _bfd_x86_elf_merge_gnu_properties
 #define elf_backend_fixup_gnu_properties \
   _bfd_x86_elf_link_fixup_gnu_properties
+#define elf_backend_size_relative_relocs \
+  _bfd_elf_x86_size_relative_relocs
+#define elf_backend_finish_relative_relocs \
+  _bfd_elf_x86_finish_relative_relocs
 
 #define ELF_P_ALIGN ELF_MINPAGESIZE
 
@@ -789,7 +919,8 @@ elf_x86_allocate_local_got_info (bfd *abfd, bfd_size_type count)
   if (local_got_refcounts == NULL)
     {
       bfd_size_type size = count * (sizeof (bfd_signed_vma)
-				    + sizeof (bfd_vma) + sizeof(char));
+				    + sizeof (bfd_vma)
+				    + 2 * sizeof(char));
       local_got_refcounts = (bfd_signed_vma *) bfd_zalloc (abfd, size);
       if (local_got_refcounts == NULL)
 	return false;
@@ -798,6 +929,8 @@ elf_x86_allocate_local_got_info (bfd *abfd, bfd_size_type count)
 	(bfd_vma *) (local_got_refcounts + count);
       elf_x86_local_got_tls_type (abfd) =
 	(char *) (local_got_refcounts + 2 * count);
+      elf_x86_relative_reloc_done (abfd) =
+	((char *) (local_got_refcounts + 2 * count)) + count;
     }
   return true;
 }
-- 
2.33.1


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 09/10] ld: Add simple DT_RELR tests
  2022-01-07 19:06 [PATCH 0/10] ld: Implement DT_RELR for x86 H.J. Lu
                   ` (7 preceding siblings ...)
  2022-01-07 19:06 ` [PATCH 08/10] x86: Add DT_RELR support H.J. Lu
@ 2022-01-07 19:06 ` H.J. Lu
  2022-01-08  2:39   ` Fangrui Song
  2022-01-08  8:37   ` Fangrui Song
  2022-01-07 19:06 ` [PATCH 10/10] ld: Add glibc dependency for DT_RELR H.J. Lu
  2022-01-07 23:45 ` [PATCH 0/10] ld: Implement DT_RELR for x86 Fangrui Song
  10 siblings, 2 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-07 19:06 UTC (permalink / raw)
  To: binutils; +Cc: Nick Clifton, Alan Modra, libc-alpha

	* testsuite/ld-elf/dt-relr-1.s: New file.
	* testsuite/ld-elf/dt-relr-1a.d: Likewise.
	* testsuite/ld-elf/dt-relr-1b.d: Likewise.
	* testsuite/ld-elf/dt-relr-1c.d: Likewise.
	* testsuite/ld-elf/dt-relr-2.s: Likewise.
	* testsuite/ld-elf/dt-relr-2a.d: Likewise.
	* testsuite/ld-elf/dt-relr-2b.d: Likewise.
	* testsuite/ld-elf/dt-relr-2c.d: Likewise.
	* testsuite/ld-elf/dt-relr-2d.d: Likewise.
	* testsuite/ld-elf/dt-relr-2e.d: Likewise.
	* testsuite/ld-elf/dt-relr-2f.d: Likewise.
	* testsuite/ld-elf/dt-relr-2g.d: Likewise.
	* testsuite/ld-elf/dt-relr-2h.d: Likewise.
---
 ld/testsuite/ld-elf/dt-relr-1.s  | 13 +++++++++++++
 ld/testsuite/ld-elf/dt-relr-1a.d | 10 ++++++++++
 ld/testsuite/ld-elf/dt-relr-1b.d |  9 +++++++++
 ld/testsuite/ld-elf/dt-relr-1c.d |  9 +++++++++
 ld/testsuite/ld-elf/dt-relr-2.s  | 20 ++++++++++++++++++++
 ld/testsuite/ld-elf/dt-relr-2a.d | 10 ++++++++++
 ld/testsuite/ld-elf/dt-relr-2b.d | 17 +++++++++++++++++
 ld/testsuite/ld-elf/dt-relr-2c.d | 17 +++++++++++++++++
 ld/testsuite/ld-elf/dt-relr-2d.d |  9 +++++++++
 ld/testsuite/ld-elf/dt-relr-2e.d |  9 +++++++++
 ld/testsuite/ld-elf/dt-relr-2f.d |  8 ++++++++
 ld/testsuite/ld-elf/dt-relr-2g.d |  9 +++++++++
 ld/testsuite/ld-elf/dt-relr-2h.d |  9 +++++++++
 13 files changed, 149 insertions(+)
 create mode 100644 ld/testsuite/ld-elf/dt-relr-1.s
 create mode 100644 ld/testsuite/ld-elf/dt-relr-1a.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-1b.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-1c.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2.s
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2a.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2b.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2c.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2d.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2e.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2f.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2g.d
 create mode 100644 ld/testsuite/ld-elf/dt-relr-2h.d

diff --git a/ld/testsuite/ld-elf/dt-relr-1.s b/ld/testsuite/ld-elf/dt-relr-1.s
new file mode 100644
index 00000000000..18486d3acb2
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-1.s
@@ -0,0 +1,13 @@
+	.text
+	.p2align 3
+	.globl _start
+_start:
+	.byte 0
+
+	.data
+	.p2align 3
+	.globl data
+data:
+	.byte 0
+	//  Offset is not a multiple of 2.  Don't use DT_RELR.
+	.dc.a __ehdr_start + 10
diff --git a/ld/testsuite/ld-elf/dt-relr-1a.d b/ld/testsuite/ld-elf/dt-relr-1a.d
new file mode 100644
index 00000000000..55c93cefb59
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-1a.d
@@ -0,0 +1,10 @@
+#source: dt-relr-1.s
+#ld: -e _start $DT_RELR_LDFLAGS
+#readelf: -rW -d
+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
+
+#...
+There is no dynamic section in this file.
+#...
+There are no relocations in this file.
+#pass
diff --git a/ld/testsuite/ld-elf/dt-relr-1b.d b/ld/testsuite/ld-elf/dt-relr-1b.d
new file mode 100644
index 00000000000..2b78f75d378
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-1b.d
@@ -0,0 +1,9 @@
+#source: dt-relr-1.s
+#ld: -e _start -pie $DT_RELR_LDFLAGS
+#readelf: -rW -d
+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
+
+#failif
+#...
+Relocation section '\.relr\.dyn' at offset .*
+#pass
diff --git a/ld/testsuite/ld-elf/dt-relr-1c.d b/ld/testsuite/ld-elf/dt-relr-1c.d
new file mode 100644
index 00000000000..14f6cda6832
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-1c.d
@@ -0,0 +1,9 @@
+#source: dt-relr-1.s
+#ld: -shared $DT_RELR_LDFLAGS
+#readelf: -rW -d
+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
+
+#failif
+#...
+Relocation section '\.relr\.dyn' at offset .*
+#pass
diff --git a/ld/testsuite/ld-elf/dt-relr-2.s b/ld/testsuite/ld-elf/dt-relr-2.s
new file mode 100644
index 00000000000..c3917ee8c3a
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-2.s
@@ -0,0 +1,20 @@
+	.text
+	.p2align 3
+	.globl _start
+_start:
+	.byte 0
+
+	.data
+	.p2align 3
+	.globl data
+data:
+
+	.dc.a .data
+	.dc.a 0
+	.dc.a data + 2
+	.dc.a __ehdr_start + 4
+	.dc.a __ehdr_start + 9
+
+	.byte 0
+	//  Offset is not a multiple of 2.  Don't use DT_RELR.
+	.dc.a __ehdr_start + 10
diff --git a/ld/testsuite/ld-elf/dt-relr-2a.d b/ld/testsuite/ld-elf/dt-relr-2a.d
new file mode 100644
index 00000000000..31ef9e8e80e
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-2a.d
@@ -0,0 +1,10 @@
+#source: dt-relr-2.s
+#ld: -e _start $DT_RELR_LDFLAGS
+#readelf: -rW -d
+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
+
+#...
+There is no dynamic section in this file.
+#...
+There are no relocations in this file.
+#pass
diff --git a/ld/testsuite/ld-elf/dt-relr-2b.d b/ld/testsuite/ld-elf/dt-relr-2b.d
new file mode 100644
index 00000000000..7c401732a56
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-2b.d
@@ -0,0 +1,17 @@
+#source: dt-relr-2.s
+#ld: -e _start -pie $DT_RELR_LDFLAGS
+#readelf: -rW -d
+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
+
+#...
+ 0x[0-9a-f]+ \(RELR\)    +0x[0-9a-f]+
+ 0x[0-9a-f]+ \(RELRSZ\)  +(8|16) \(bytes\)
+ 0x[0-9a-f]+ \(RELRENT\) +(4|8) \(bytes\)
+#...
+Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 1 entry:
+#...
+[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .*
+#...
+Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+  4 offsets
+#pass
diff --git a/ld/testsuite/ld-elf/dt-relr-2c.d b/ld/testsuite/ld-elf/dt-relr-2c.d
new file mode 100644
index 00000000000..63877b2f90f
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-2c.d
@@ -0,0 +1,17 @@
+#source: dt-relr-2.s
+#ld: -shared $DT_RELR_LDFLAGS
+#readelf: -rW -d
+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
+
+#...
+ 0x[0-9a-f]+ \(RELR\)    +0x[0-9a-f]+
+ 0x[0-9a-f]+ \(RELRSZ\)  +(8|16) \(bytes\)
+ 0x[0-9a-f]+ \(RELRENT\) +(4|8) \(bytes\)
+#...
+Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+#...
+[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .*
+#...
+Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+  3 offsets
+#pass
diff --git a/ld/testsuite/ld-elf/dt-relr-2d.d b/ld/testsuite/ld-elf/dt-relr-2d.d
new file mode 100644
index 00000000000..270a901f1a6
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-2d.d
@@ -0,0 +1,9 @@
+#source: dt-relr-2.s
+#ld: -e _start -pie $DT_RELR_LDFLAGS --no-relax
+#readelf: -rW -d
+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
+
+#failif
+#...
+Relocation section '\.relr\.dyn' at offset .*
+#pass
diff --git a/ld/testsuite/ld-elf/dt-relr-2e.d b/ld/testsuite/ld-elf/dt-relr-2e.d
new file mode 100644
index 00000000000..79ea62b096a
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-2e.d
@@ -0,0 +1,9 @@
+#source: dt-relr-2.s
+#ld: -e _start -pie $DT_RELR_LDFLAGS -z nocombreloc
+#readelf: -rW -d
+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
+
+#failif
+#...
+Relocation section '\.relr\.dyn' at offset .*
+#pass
diff --git a/ld/testsuite/ld-elf/dt-relr-2f.d b/ld/testsuite/ld-elf/dt-relr-2f.d
new file mode 100644
index 00000000000..4ad592f71fb
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-2f.d
@@ -0,0 +1,8 @@
+#source: dt-relr-2.s
+#ld: -r $DT_RELR_LDFLAGS
+#readelf: -rW
+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
+
+#...
+Relocation section '\.rel(a|)\.data' at offset 0x[0-9a-f]+ contains 5 entries:
+#pass
diff --git a/ld/testsuite/ld-elf/dt-relr-2g.d b/ld/testsuite/ld-elf/dt-relr-2g.d
new file mode 100644
index 00000000000..78e370068af
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-2g.d
@@ -0,0 +1,9 @@
+#source: dt-relr-2.s
+#ld: -e _start -pie $NO_DT_RELR_LDFLAGS
+#readelf: -rW -d
+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
+
+#failif
+#...
+Relocation section '\.relr\.dyn' at offset .*
+#pass
diff --git a/ld/testsuite/ld-elf/dt-relr-2h.d b/ld/testsuite/ld-elf/dt-relr-2h.d
new file mode 100644
index 00000000000..312373fb179
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-2h.d
@@ -0,0 +1,9 @@
+#source: dt-relr-2.s
+#ld: -e _start -shared $NO_DT_RELR_LDFLAGS
+#readelf: -rW -d
+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
+
+#failif
+#...
+Relocation section '\.relr\.dyn' at offset .*
+#pass
-- 
2.33.1


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 10/10] ld: Add glibc dependency for DT_RELR
  2022-01-07 19:06 [PATCH 0/10] ld: Implement DT_RELR for x86 H.J. Lu
                   ` (8 preceding siblings ...)
  2022-01-07 19:06 ` [PATCH 09/10] ld: Add simple DT_RELR tests H.J. Lu
@ 2022-01-07 19:06 ` H.J. Lu
  2022-01-08  4:43   ` Fangrui Song
  2022-01-07 23:45 ` [PATCH 0/10] ld: Implement DT_RELR for x86 Fangrui Song
  10 siblings, 1 reply; 31+ messages in thread
From: H.J. Lu @ 2022-01-07 19:06 UTC (permalink / raw)
  To: binutils; +Cc: Nick Clifton, Alan Modra, libc-alpha

When DT_RELR is enabled, to avoid random run-time crash with older glibc
binaries without DT_RELR support, add a GLIBC_ABI_DT_RELR symbol version,
which is provided by glibc with DT_RELR support, dependency on the shared
C library if it provides a GLIBC_2.XX symbol version.

bfd/

	* elflink.c (elf_link_add_dt_relr_dependency): New function.
	(bfd_elf_size_dynamic_sections): Call
	elf_link_add_dt_relr_dependency if DT_RELR is enabled.

ld/

	* ld.texi: Mention GLIBC_ABI_DT_RELR in -z pack-relative-relocs
	entry.
	* testsuite/ld-elf/dt-relr-glibc-1.c: New file.
	* testsuite/ld-elf/dt-relr-glibc-1a.rd: Likewise.
	* testsuite/ld-elf/dt-relr-glibc-1b.rd: Likewise.
	* testsuite/ld-elf/dt-relr.exp: Likewise.
---
 bfd/elflink.c                           | 86 +++++++++++++++++++++++++
 ld/ld.texi                              |  4 +-
 ld/testsuite/ld-elf/dt-relr-glibc-1.c   | 11 ++++
 ld/testsuite/ld-elf/dt-relr-glibc-1a.rd |  4 ++
 ld/testsuite/ld-elf/dt-relr-glibc-1b.rd |  7 ++
 ld/testsuite/ld-elf/dt-relr.exp         | 44 +++++++++++++
 6 files changed, 155 insertions(+), 1 deletion(-)
 create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1.c
 create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1a.rd
 create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1b.rd
 create mode 100644 ld/testsuite/ld-elf/dt-relr.exp

diff --git a/bfd/elflink.c b/bfd/elflink.c
index 31b13f5df7a..05ac1cb7a63 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -2213,6 +2213,85 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
   return true;
 }
 \f
+/* Return true if GLIBC_ABI_DT_RELR is added to the list of version
+   dependencies successfully.  GLIBC_ABI_DT_RELR will be put into the
+   .gnu.version_r section.  */
+
+static bool
+elf_link_add_dt_relr_dependency (struct elf_find_verdep_info *rinfo)
+{
+  bfd *glibc_bfd = NULL;
+  Elf_Internal_Verneed *t;
+  Elf_Internal_Vernaux *a;
+  size_t amt;
+  const char *relr = "GLIBC_ABI_DT_RELR";
+
+  /* See if we already know about GLIBC_PRIVATE_DT_RELR.  */
+  for (t = elf_tdata (rinfo->info->output_bfd)->verref;
+       t != NULL;
+       t = t->vn_nextref)
+    {
+      const char *soname = bfd_elf_get_dt_soname (t->vn_bfd);
+      /* Skip the shared library if it isn't libc.so.  */
+      if (!soname || !startswith (soname, "libc.so."))
+	continue;
+
+      for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+	{
+	  /* Return if GLIBC_PRIVATE_DT_RELR dependency has been
+	     added.  */
+	  if (a->vna_nodename == relr
+	      || strcmp (a->vna_nodename, relr) == 0)
+	    return true;
+
+	  /* Check if libc.so provides GLIBC_2.XX version.  */
+	  if (!glibc_bfd && startswith (a->vna_nodename, "GLIBC_2."))
+	    glibc_bfd = t->vn_bfd;
+	}
+
+      break;
+    }
+
+  /* Skip if it isn't linked against glibc.  */
+  if (glibc_bfd == NULL)
+    return true;
+
+  /* This is a new version.  Add it to tree we are building.  */
+  if (t == NULL)
+    {
+      amt = sizeof *t;
+      t = (Elf_Internal_Verneed *) bfd_zalloc (rinfo->info->output_bfd,
+					       amt);
+      if (t == NULL)
+	{
+	  rinfo->failed = true;
+	  return false;
+	}
+
+      t->vn_bfd = glibc_bfd;
+      t->vn_nextref = elf_tdata (rinfo->info->output_bfd)->verref;
+      elf_tdata (rinfo->info->output_bfd)->verref = t;
+    }
+
+  amt = sizeof *a;
+  a = (Elf_Internal_Vernaux *) bfd_zalloc (rinfo->info->output_bfd, amt);
+  if (a == NULL)
+    {
+      rinfo->failed = true;
+      return false;
+    }
+
+  a->vna_nodename = relr;
+  a->vna_flags = 0;
+  a->vna_nextptr = t->vn_auxptr;
+  a->vna_other = rinfo->vers + 1;
+  ++rinfo->vers;
+
+  t->vn_auxptr = a;
+
+  return true;
+}
+
 /* Look through the symbols which are defined in other shared
    libraries and referenced here.  Update the list of version
    dependencies.  This will be put into the .gnu.version_r section.
@@ -6940,6 +7019,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       if (sinfo.failed)
 	return false;
 
+      if (info->enable_dt_relr)
+	{
+	  elf_link_add_dt_relr_dependency (&sinfo);
+	  if (sinfo.failed)
+	    return false;
+	}
+
       if (elf_tdata (output_bfd)->verref == NULL)
 	s->flags |= SEC_EXCLUDE;
       else
diff --git a/ld/ld.texi b/ld/ld.texi
index 457089ec06a..a16657ddb45 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -1439,7 +1439,9 @@ and shared library.  It adds @code{DT_RELR}, @code{DT_RELRSZ} and
 building position-dependent executable and relocatable output.  This
 option also implies @option{combreloc} and @option{--relax}.
 @option{nopack-relative-relocs} is the default, which disables
-compact relative relocation.  Supported for i386 and x86-64.
+compact relative relocation.  When linked against the GNU C Library,
+a GLIBC_ABI_DT_RELR symbol version dependency on the shared C Library
+is added to the output.  Supported for i386 and x86-64.
 
 @item relro
 @itemx norelro
diff --git a/ld/testsuite/ld-elf/dt-relr-glibc-1.c b/ld/testsuite/ld-elf/dt-relr-glibc-1.c
new file mode 100644
index 00000000000..beacffe29e7
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-glibc-1.c
@@ -0,0 +1,11 @@
+#define REL(n) \
+  static int data##n; \
+  void *p##n = &data##n;
+
+REL(1)
+REL(2)
+REL(3)
+REL(4)
+REL(5)
+REL(6)
+REL(7)
diff --git a/ld/testsuite/ld-elf/dt-relr-glibc-1a.rd b/ld/testsuite/ld-elf/dt-relr-glibc-1a.rd
new file mode 100644
index 00000000000..51bda5d70a1
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-glibc-1a.rd
@@ -0,0 +1,4 @@
+#failif
+#...
+  0x[a-f0-9]+:   Name: GLIBC_ABI_DT_RELR  Flags: none  Version: [0-9]+
+#...
diff --git a/ld/testsuite/ld-elf/dt-relr-glibc-1b.rd b/ld/testsuite/ld-elf/dt-relr-glibc-1b.rd
new file mode 100644
index 00000000000..6556a6d939e
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr-glibc-1b.rd
@@ -0,0 +1,7 @@
+#...
+Version needs section '.gnu.version_r' contains 1 entry:
+ Addr: 0x[0-9a-f]+ +Offset: 0x[0-9a-f]+ +Link: +[0-9]+ +\(.dynstr\)
+ +0+: Version: 1 +File: libc\.so\.6(|\.1) +Cnt: +[0-9]+
+#...
+  0x[a-f0-9]+:   Name: GLIBC_ABI_DT_RELR  Flags: none  Version: [0-9]+
+#pass
diff --git a/ld/testsuite/ld-elf/dt-relr.exp b/ld/testsuite/ld-elf/dt-relr.exp
new file mode 100644
index 00000000000..51d21e400ab
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-relr.exp
@@ -0,0 +1,44 @@
+# Expect script for DT_RELR.
+#   Copyright (C) 2022 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# Linux tests.
+if { ![istarget "*-*-linux*"] } {
+    return
+}
+
+run_cc_link_tests [list \
+    [list \
+	"Build dt-relr-glibc-1a.so" \
+	"-shared $NO_DT_RELR_CC_LDFLAGS" \
+	"-fPIC" \
+	{ dt-relr-glibc-1.c } \
+	{{readelf {--version-info} dt-relr-glibc-1a.rd}} \
+	"glibc-relr-1a.so" \
+    ] \
+    [list \
+	"Build dt-relr-glibc-1b.so" \
+	"-shared $DT_RELR_CC_LDFLAGS" \
+	"-fPIC" \
+	{ dt-relr-glibc-1.c } \
+	{{readelf {-W --version-info} dt-relr-glibc-1b.rd}} \
+	"dt-relr-glibc-1b.so" \
+    ] \
+]
-- 
2.33.1


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 0/10] ld: Implement DT_RELR for x86
  2022-01-07 19:06 [PATCH 0/10] ld: Implement DT_RELR for x86 H.J. Lu
                   ` (9 preceding siblings ...)
  2022-01-07 19:06 ` [PATCH 10/10] ld: Add glibc dependency for DT_RELR H.J. Lu
@ 2022-01-07 23:45 ` Fangrui Song
  2022-01-07 23:56   ` H.J. Lu
  10 siblings, 1 reply; 31+ messages in thread
From: Fangrui Song @ 2022-01-07 23:45 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, libc-alpha, Nick Clifton, Alan Modra

On 2022-01-07, H.J. Lu via Libc-alpha wrote:
>Hi Nick,
>
>I'd like to enable DT_RELR for x86 in binutils 2.38.
>
>
>H.J.
>---

Thanks for the patch!

Is the Clang crash
https://sourceware.org/pipermail/libc-alpha/2022-January/134992.html
fixed now?


> 10/10 ld: Add glibc dependency for DT_RELR
>
> if (!glibc_bfd && startswith (a->vna_nodename, "GLIBC_2."))

Thanks for adding the GLIBC_ABI_DT_RELR verneed only if GLIBC_2.* exists, this will make
musl/FreeBSD/NetBSD/etc happy.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 0/10] ld: Implement DT_RELR for x86
  2022-01-07 23:45 ` [PATCH 0/10] ld: Implement DT_RELR for x86 Fangrui Song
@ 2022-01-07 23:56   ` H.J. Lu
  2022-01-08  1:31     ` Fangrui Song
  0 siblings, 1 reply; 31+ messages in thread
From: H.J. Lu @ 2022-01-07 23:56 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils, GNU C Library, Nick Clifton, Alan Modra

On Fri, Jan 7, 2022 at 3:46 PM Fangrui Song <maskray@google.com> wrote:
>
> On 2022-01-07, H.J. Lu via Libc-alpha wrote:
> >Hi Nick,
> >
> >I'd like to enable DT_RELR for x86 in binutils 2.38.
> >
> >
> >H.J.
> >---
>
> Thanks for the patch!
>
> Is the Clang crash
> https://sourceware.org/pipermail/libc-alpha/2022-January/134992.html
> fixed now?
>

It should be fixed.  Please try my current DT_RELR branch.

> > 10/10 ld: Add glibc dependency for DT_RELR
> >
> > if (!glibc_bfd && startswith (a->vna_nodename, "GLIBC_2."))
>
> Thanks for adding the GLIBC_ABI_DT_RELR verneed only if GLIBC_2.* exists, this will make
> musl/FreeBSD/NetBSD/etc happy.


-- 
H.J.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 0/10] ld: Implement DT_RELR for x86
  2022-01-07 23:56   ` H.J. Lu
@ 2022-01-08  1:31     ` Fangrui Song
  2022-01-08  1:55       ` H.J. Lu
  0 siblings, 1 reply; 31+ messages in thread
From: Fangrui Song @ 2022-01-08  1:31 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Fangrui Song, GNU C Library, Binutils

On 2022-01-07, H.J. Lu via Binutils wrote:
>On Fri, Jan 7, 2022 at 3:46 PM Fangrui Song <maskray@google.com> wrote:
>>
>> On 2022-01-07, H.J. Lu via Libc-alpha wrote:
>> >Hi Nick,
>> >
>> >I'd like to enable DT_RELR for x86 in binutils 2.38.
>> >
>> >
>> >H.J.
>> >---
>>
>> Thanks for the patch!
>>
>> Is the Clang crash
>> https://sourceware.org/pipermail/libc-alpha/2022-January/134992.html
>> fixed now?
>>
>
>It should be fixed.  Please try my current DT_RELR branch.

Thanks. It works.

% rm /tmp/out/custom1/clang
% ninja -C /tmp/out/custom1/clang -v  # find the linker command line
% <linker-command-line> -Wl,--reproduce=/tmp/clang-relassert.tar
% cd /tmp && tar xf clang-relassert.tar && cd clang-relassert
# Remove --chroot from response.txt

# Managed to compile a file with the linked clang 
% ~/Dev/binutils-gdb/out/release/ld/ld-new -z pack-relative-relocs @response.txt -o bfd.relr 
% LD_LIBRARY_PATH=/tmp/glibc/lld/lib:/usr/lib/x86_64-linux-gnu /tmp/glibc/lld/lib/ld-linux-x86-64.so.2 ./bfd.relr -c /tmp/c/a.c -O2 


There are still quite a few even-address R_X86_64_RELATIVE relocations.
Any idea why they are present?


% ~/Dev/binutils-gdb/out/release/binutils/readelf -r bfd.relr
...
Relocation section '.rela.dyn' at offset 0x5fb400 contains 3133 entries:
   Offset          Info           Type           Sym. Value    Sym. Name + Addend
000009902608  000000000008 R_X86_64_RELATIVE                    9281940
000009902610  000000000008 R_X86_64_RELATIVE                    7a4d565
000009902618  000000000008 R_X86_64_RELATIVE                    91acf98
...
Relocation section '.relr.dyn' at offset 0x60f6e0 contains 19910 entries:
   535577 offsets
0000000008f83f58
0000000008f83f60
0000000008f83f68
...

>
>> > 10/10 ld: Add glibc dependency for DT_RELR
>> >
>> > if (!glibc_bfd && startswith (a->vna_nodename, "GLIBC_2."))
>>
>> Thanks for adding the GLIBC_ABI_DT_RELR verneed only if GLIBC_2.* exists, this will make
>> musl/FreeBSD/NetBSD/etc happy.

Does your DT_RELR patch have something like this?

+    // Don't allow the section to shrink, otherwise the size of the section can
+    // oscillate infinitely. Trailing 1s do not decode to more relocations.
+    if (entries_.size() < old_size)
+      entries_.resize(old_size, 1);

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 0/10] ld: Implement DT_RELR for x86
  2022-01-08  1:31     ` Fangrui Song
@ 2022-01-08  1:55       ` H.J. Lu
  2022-01-08 18:30         ` H.J. Lu
  0 siblings, 1 reply; 31+ messages in thread
From: H.J. Lu @ 2022-01-08  1:55 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Fangrui Song, GNU C Library, Binutils

On Fri, Jan 7, 2022 at 5:31 PM Fangrui Song <i@maskray.me> wrote:
>
> On 2022-01-07, H.J. Lu via Binutils wrote:
> >On Fri, Jan 7, 2022 at 3:46 PM Fangrui Song <maskray@google.com> wrote:
> >>
> >> On 2022-01-07, H.J. Lu via Libc-alpha wrote:
> >> >Hi Nick,
> >> >
> >> >I'd like to enable DT_RELR for x86 in binutils 2.38.
> >> >
> >> >
> >> >H.J.
> >> >---
> >>
> >> Thanks for the patch!
> >>
> >> Is the Clang crash
> >> https://sourceware.org/pipermail/libc-alpha/2022-January/134992.html
> >> fixed now?
> >>
> >
> >It should be fixed.  Please try my current DT_RELR branch.
>
> Thanks. It works.
>
> % rm /tmp/out/custom1/clang
> % ninja -C /tmp/out/custom1/clang -v  # find the linker command line
> % <linker-command-line> -Wl,--reproduce=/tmp/clang-relassert.tar
> % cd /tmp && tar xf clang-relassert.tar && cd clang-relassert
> # Remove --chroot from response.txt
>
> # Managed to compile a file with the linked clang
> % ~/Dev/binutils-gdb/out/release/ld/ld-new -z pack-relative-relocs @response.txt -o bfd.relr
> % LD_LIBRARY_PATH=/tmp/glibc/lld/lib:/usr/lib/x86_64-linux-gnu /tmp/glibc/lld/lib/ld-linux-x86-64.so.2 ./bfd.relr -c /tmp/c/a.c -O2
>
>
> There are still quite a few even-address R_X86_64_RELATIVE relocations.
> Any idea why they are present?

ld can generate R_X86_64_RELATIVE in elf_x86_64_finish_dynamic_symbol:

     else if (bfd_link_pic (info)
               && SYMBOL_REFERENCES_LOCAL_P (info, h))
        {
          if (!SYMBOL_DEFINED_NON_SHARED_P (h))
            return false;
          BFD_ASSERT((h->got.offset & 1) != 0);
          rela.r_info = htab->r_info (0, R_X86_64_RELATIVE);
          rela.r_addend = (h->root.u.def.value
                           + h->root.u.def.section->output_section->vma
                           + h->root.u.def.section->output_offset);
          relative_reloc_name = "R_X86_64_RELATIVE";
        }

This case isn't handled yet.

>
> % ~/Dev/binutils-gdb/out/release/binutils/readelf -r bfd.relr
> ...
> Relocation section '.rela.dyn' at offset 0x5fb400 contains 3133 entries:
>    Offset          Info           Type           Sym. Value    Sym. Name + Addend
> 000009902608  000000000008 R_X86_64_RELATIVE                    9281940
> 000009902610  000000000008 R_X86_64_RELATIVE                    7a4d565
> 000009902618  000000000008 R_X86_64_RELATIVE                    91acf98
> ...
> Relocation section '.relr.dyn' at offset 0x60f6e0 contains 19910 entries:
>    535577 offsets
> 0000000008f83f58
> 0000000008f83f60
> 0000000008f83f68
> ...
>
> >
> >> > 10/10 ld: Add glibc dependency for DT_RELR
> >> >
> >> > if (!glibc_bfd && startswith (a->vna_nodename, "GLIBC_2."))
> >>
> >> Thanks for adding the GLIBC_ABI_DT_RELR verneed only if GLIBC_2.* exists, this will make
> >> musl/FreeBSD/NetBSD/etc happy.
>
> Does your DT_RELR patch have something like this?
>
> +    // Don't allow the section to shrink, otherwise the size of the section can
> +    // oscillate infinitely. Trailing 1s do not decode to more relocations.
> +    if (entries_.size() < old_size)
> +      entries_.resize(old_size, 1);

     if (dt_relr_bitmap_count > new_count)
        {
          /* Don't shrink the DT_RELR section size to avoid section
             layout oscillation.  Instead, pad the DT_RELR bitmap with
             1s which do not decode to more relocations.  */

          htab->dt_relr_bitmap.count = dt_relr_bitmap_count;
          count = dt_relr_bitmap_count - new_count;
          for (i = 0; i < count; i++)
            htab->dt_relr_bitmap.u.elf64[new_count + i] = 1;
        }


-- 
H.J.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 05/10] ld: Initial DT_RELR support
  2022-01-07 19:06 ` [PATCH 05/10] ld: Initial DT_RELR support H.J. Lu
@ 2022-01-08  2:10   ` Fangrui Song
  2022-01-08  2:42     ` H.J. Lu
  2022-01-08  8:30   ` Fangrui Song
  1 sibling, 1 reply; 31+ messages in thread
From: Fangrui Song @ 2022-01-08  2:10 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, libc-alpha

On 2022-01-07, H.J. Lu via Binutils wrote:
>Add a -z pack-relative-relocs option to enable DT_RELR and create a
>relr.dyn section for DT_RELR.
>
>-z pack-relative-relocs implies -z combreloc and --relax.  --no-relax
>and -z nocombreloc imply -z nopack-relative-relocs.
>
>-z pack-relative-relocs is chosen over the similar option in lld,
>--pack-dyn-relocs=relr, to implement a glibc binary lockout mechanism
>with a special glibc version symbol, to avoid random crashes of DT_RELR
>binaries with the existing glibc binaries.

Why does --no-relax suppress  -z nopack-relative-relocs?

My mental model is that --relax is for GOTPCRELX/TLS optimization/RISC-V
relaxation/AArch64 GOT optimization/(hopefully PowerPC64 TOC
optimization)/etc. It should be orthogonal to RELR. It is true that
both RISC-V relaxation/RELR need to compute the layouts more than once,
but other passes technically don't need to be coupled with layout
computation.

People specifying --no-relax may work around potential bugs, but they
may not want to lose the benefit of RELR.

>bfd/
>
>	* elf-bfd.h (elf_link_hash_table): Add srelrdyn.
>	* elflink.c (_bfd_elf_link_create_dynamic_sections): Create a
>	.relr.dyn section for DT_RELR.
>
>include/
>
>	* bfdlink.h (bfd_link_info): Add enable_dt_relr.
>
>ld/
>
>	* News: Mention -z pack-relative-relocs and
>	-z nopack-relative-relocs.
>	* ld.texi: Document -z pack-relative-relocs and
>	-z nopack-relative-relocs.
>	* ldelf.c (ldelf_after_parse): Disable DT_RELR if not building
>	PIE nor shared library.  Add 3 spare dynamic tags for DT_RELR,
>	DT_RELRSZ and DT_RELRENT.
>	* lexsup.c (parse_args): Disable DT_RELR for --no-relax.
>	* emulparams/elf32_x86_64.sh: Source dt-relr.sh.
>	* emulparams/elf_i386.sh: Likewise.
>	* emulparams/elf_x86_64.sh: Likewise.
>	* emulparams/dt-relr.sh: New file.
>	* emultempl/elf.em (gld${EMULATION_NAME}_handle_option): Disable
>	DT_RELR for -z nocombreloc.
>	* scripttempl/elf.sc: Support .relr.dyn.
>---
> bfd/elf-bfd.h                 |  1 +
> bfd/elflink.c                 | 11 +++++++++++
> include/bfdlink.h             |  4 ++++
> ld/NEWS                       |  3 +++
> ld/emulparams/dt-relr.sh      | 21 +++++++++++++++++++++
> ld/emulparams/elf32_x86_64.sh |  1 +
> ld/emulparams/elf_i386.sh     |  1 +
> ld/emulparams/elf_x86_64.sh   |  1 +
> ld/emultempl/elf.em           |  5 ++++-
> ld/ld.texi                    | 14 +++++++++++++-
> ld/ldelf.c                    | 13 +++++++++++++
> ld/lexsup.c                   |  1 +
> ld/scripttempl/elf.sc         |  4 ++++
> 13 files changed, 78 insertions(+), 2 deletions(-)
> create mode 100644 ld/emulparams/dt-relr.sh
>
>diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
>index c4d2ef00d6b..4e73d79ee77 100644
>--- a/bfd/elf-bfd.h
>+++ b/bfd/elf-bfd.h
>@@ -707,6 +707,7 @@ struct elf_link_hash_table
>   asection *irelplt;
>   asection *irelifunc;
>   asection *dynsym;
>+  asection *srelrdyn;
> };
>
> /* Returns TRUE if the hash table is a struct elf_link_hash_table.  */
>diff --git a/bfd/elflink.c b/bfd/elflink.c
>index bea413ec24e..d51b00b6c10 100644
>--- a/bfd/elflink.c
>+++ b/bfd/elflink.c
>@@ -359,6 +359,17 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
> 	elf_section_data (s)->this_hdr.sh_entsize = 4;
>     }
>
>+  if (info->enable_dt_relr)
>+    {
>+      s = bfd_make_section_anyway_with_flags (abfd, ".relr.dyn",
>+					      (bed->dynamic_sec_flags
>+					       | SEC_READONLY));
>+      if (s == NULL
>+	  || !bfd_set_section_alignment (s, bed->s->log_file_align))
>+	return false;
>+      elf_hash_table (info)->srelrdyn = s;
>+    }
>+
>   /* Let the backend create the rest of the sections.  This lets the
>      backend set the right flags.  The backend will normally create
>      the .got and .plt sections.  */
>diff --git a/include/bfdlink.h b/include/bfdlink.h
>index 01f57c22edf..92e3e32360b 100644
>--- a/include/bfdlink.h
>+++ b/include/bfdlink.h
>@@ -413,6 +413,10 @@ struct bfd_link_info
>   /* TRUE if PT_GNU_RELRO segment should be created.  */
>   unsigned int relro: 1;
>
>+  /* TRUE if DT_RELR should be enabled for compact relative
>+     relocations.  */
>+  unsigned int enable_dt_relr: 1;
>+
>   /* TRUE if separate code segment should be created.  */
>   unsigned int separate_code: 1;
>
>diff --git a/ld/NEWS b/ld/NEWS
>index 5d3d80dbbba..77c716b577d 100644
>--- a/ld/NEWS
>+++ b/ld/NEWS
>@@ -1,5 +1,8 @@
> -*- text -*-
>
>+* Add -z pack-relative-relocs/-z no pack-relative-relocs to x86 ELF
>+  linker to pack relative relocations in the DT_RELR section.
>+
> * Add support for the LoongArch architecture.
>
> * Add -z indirect-extern-access/-z noindirect-extern-access to x86 ELF
>diff --git a/ld/emulparams/dt-relr.sh b/ld/emulparams/dt-relr.sh
>new file mode 100644
>index 00000000000..ed93ee2b5c2
>--- /dev/null
>+++ b/ld/emulparams/dt-relr.sh
>@@ -0,0 +1,21 @@
>+HAVE_DT_RELR=yes
>+PARSE_AND_LIST_OPTIONS_PACK_RELATIVE_RELOCS='
>+  fprintf (file, _("\
>+  -z pack-relative-relocs     Pack relative relocations\n"));
>+  fprintf (file, _("\
>+  -z nopack-relative-relocs   Do not pack relative relocations (default)\n"));
>+'
>+
>+PARSE_AND_LIST_ARGS_CASE_Z_PACK_RELATIVE_RELOCS='
>+      else if (strcmp (optarg, "pack-relative-relocs") == 0)
>+	{
>+	  link_info.enable_dt_relr = true;
>+	  link_info.combreloc = true;
>+	}
>+      else if (strcmp (optarg, "nopack-relative-relocs") == 0)
>+	link_info.enable_dt_relr = false;
>+'
>+
>+
>+PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_PACK_RELATIVE_RELOCS"
>+PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_PACK_RELATIVE_RELOCS"
>diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh
>index ac0a7aa6dcf..4bff41287c1 100644
>--- a/ld/emulparams/elf32_x86_64.sh
>+++ b/ld/emulparams/elf32_x86_64.sh
>@@ -7,6 +7,7 @@ source_sh ${srcdir}/emulparams/cet.sh
> source_sh ${srcdir}/emulparams/x86-report-relative.sh
> source_sh ${srcdir}/emulparams/x86-64-level.sh
> source_sh ${srcdir}/emulparams/static.sh
>+source_sh ${srcdir}/emulparams/dt-relr.sh
> SCRIPT_NAME=elf
> ELFSIZE=32
> OUTPUT_FORMAT="elf32-x86-64"
>diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh
>index 98532e5edbc..ae17bb4b3f7 100644
>--- a/ld/emulparams/elf_i386.sh
>+++ b/ld/emulparams/elf_i386.sh
>@@ -6,6 +6,7 @@ source_sh ${srcdir}/emulparams/cet.sh
> source_sh ${srcdir}/emulparams/x86-report-relative.sh
> source_sh ${srcdir}/emulparams/x86-64-level.sh
> source_sh ${srcdir}/emulparams/static.sh
>+source_sh ${srcdir}/emulparams/dt-relr.sh
> SCRIPT_NAME=elf
> OUTPUT_FORMAT="elf32-i386"
> NO_RELA_RELOCS=yes
>diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh
>index 48d0974711b..5f2743ed409 100644
>--- a/ld/emulparams/elf_x86_64.sh
>+++ b/ld/emulparams/elf_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-lam.sh
> source_sh ${srcdir}/emulparams/static.sh
>+source_sh ${srcdir}/emulparams/dt-relr.sh
> SCRIPT_NAME=elf
> ELFSIZE=64
> OUTPUT_FORMAT="elf64-x86-64"
>diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em
>index 59775260b06..7a32a4cc4d4 100644
>--- a/ld/emultempl/elf.em
>+++ b/ld/emultempl/elf.em
>@@ -822,7 +822,10 @@ fragment <<EOF
>       else if (strcmp (optarg, "combreloc") == 0)
> 	link_info.combreloc = true;
>       else if (strcmp (optarg, "nocombreloc") == 0)
>-	link_info.combreloc = false;
>+	{
>+	  link_info.combreloc = false;
>+	  link_info.enable_dt_relr = false;
>+	}
>       else if (strcmp (optarg, "nocopyreloc") == 0)
> 	link_info.nocopyreloc = true;
> EOF
>diff --git a/ld/ld.texi b/ld/ld.texi
>index edcf1772855..457089ec06a 100644
>--- a/ld/ld.texi
>+++ b/ld/ld.texi
>@@ -1242,6 +1242,7 @@ Supported for Linux/i386 and Linux/x86_64.
> @itemx nocombreloc
> Combine multiple dynamic relocation sections and sort to improve
> dynamic symbol lookup caching.  Do not do this if @samp{nocombreloc}.
>+@samp{nocombreloc} implies @samp{nopack-relative-relocs}.
>
> @item common
> @itemx nocommon
>@@ -1430,6 +1431,16 @@ called.
> @item origin
> Specify that the object requires @samp{$ORIGIN} handling in paths.
>
>+@item pack-relative-relocs
>+@itemx nopack-relative-relocs
>+Generate compact relative relocation in position-independent executable
>+and shared library.  It adds @code{DT_RELR}, @code{DT_RELRSZ} and
>+@code{DT_RELRENT} entries to the dynamic section.  It is ignored when
>+building position-dependent executable and relocatable output.  This
>+option also implies @option{combreloc} and @option{--relax}.
>+@option{nopack-relative-relocs} is the default, which disables
>+compact relative relocation.  Supported for i386 and x86-64.
>+
> @item relro
> @itemx norelro
> Create an ELF @code{PT_GNU_RELRO} segment header in the object.  This
>@@ -2215,7 +2226,8 @@ family of processors.
> @end ifset
>
> On platforms where the feature is supported, the option
>-@option{--no-relax} will disable it.
>+@option{--no-relax} will disable it and also imply
>+@option{-z nopack-relative-relocs}.
>
> On platforms where the feature is not supported, both @option{--relax}
> and @option{--no-relax} are accepted, but ignored.
>diff --git a/ld/ldelf.c b/ld/ldelf.c
>index d15f027e91a..1978ac477f5 100644
>--- a/ld/ldelf.c
>+++ b/ld/ldelf.c
>@@ -71,6 +71,19 @@ ldelf_after_parse (void)
> 	einfo (_("%P: warning: -z dynamic-undefined-weak ignored\n"));
>       link_info.dynamic_undefined_weak = 0;
>     }
>+
>+  /* Disable DT_RELR if not building PIE nor shared library.  */
>+  if (!bfd_link_pic (&link_info))
>+    link_info.enable_dt_relr = 0;
>+
>+  if (link_info.enable_dt_relr)
>+    {
>+      ENABLE_RELAXATION;
>+
>+      /* Add 3 spare tags for DT_RELR, DT_RELRSZ and DT_RELRENT.  */
>+      link_info.spare_dynamic_tags += 3;
>+    }
>+
>   after_parse_default ();
>   if (link_info.commonpagesize > link_info.maxpagesize)
>     einfo (_("%F%P: common page size (0x%v) > maximum page size (0x%v)\n"),
>diff --git a/ld/lexsup.c b/ld/lexsup.c
>index 5acc47ed5a0..3942716963a 100644
>--- a/ld/lexsup.c
>+++ b/ld/lexsup.c
>@@ -1229,6 +1229,7 @@ parse_args (unsigned argc, char **argv)
> 	  break;
> 	case OPTION_NO_RELAX:
> 	  DISABLE_RELAXATION;
>+	  link_info.enable_dt_relr = false;
> 	  break;
> 	case OPTION_RELAX:
> 	  ENABLE_RELAXATION;
>diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
>index a9a39ad402c..f3552a4a554 100644
>--- a/ld/scripttempl/elf.sc
>+++ b/ld/scripttempl/elf.sc
>@@ -10,6 +10,7 @@
> #		empty.
> #	HAVE_NOINIT - Include a .noinit output section in the script.
> #	HAVE_PERSISTENT - Include a .persistent output section in the script.
>+#	HAVE_DT_RELR - Include a .relr.dyn output section in the script.
> #	SMALL_DATA_CTOR - .ctors contains small data.
> #	SMALL_DATA_DTOR - .dtors contains small data.
> #	DATA_ADDR - if end-of-text-plus-one-page isn't right for data start
>@@ -520,6 +521,9 @@ emit_dyn()
>     fi
>   fi
>   rm -f ldscripts/dyntmp.$$
>+  if test -n "${COMBRELOC}" && test -n "${HAVE_DT_RELR}"; then
>+    echo "  .relr.dyn : { *(.relr.dyn) }"
>+  fi
> }
>
> test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn
>-- 
>2.33.1
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 09/10] ld: Add simple DT_RELR tests
  2022-01-07 19:06 ` [PATCH 09/10] ld: Add simple DT_RELR tests H.J. Lu
@ 2022-01-08  2:39   ` Fangrui Song
  2022-01-08  2:44     ` H.J. Lu
  2022-01-08  8:37   ` Fangrui Song
  1 sibling, 1 reply; 31+ messages in thread
From: Fangrui Song @ 2022-01-08  2:39 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, libc-alpha

On 2022-01-07, H.J. Lu via Binutils wrote:
>	* testsuite/ld-elf/dt-relr-1.s: New file.
>	* testsuite/ld-elf/dt-relr-1a.d: Likewise.
>	* testsuite/ld-elf/dt-relr-1b.d: Likewise.
>	* testsuite/ld-elf/dt-relr-1c.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2.s: Likewise.
>	* testsuite/ld-elf/dt-relr-2a.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2b.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2c.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2d.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2e.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2f.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2g.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2h.d: Likewise.
>---
> ld/testsuite/ld-elf/dt-relr-1.s  | 13 +++++++++++++
> ld/testsuite/ld-elf/dt-relr-1a.d | 10 ++++++++++
> ld/testsuite/ld-elf/dt-relr-1b.d |  9 +++++++++
> ld/testsuite/ld-elf/dt-relr-1c.d |  9 +++++++++
> ld/testsuite/ld-elf/dt-relr-2.s  | 20 ++++++++++++++++++++
> ld/testsuite/ld-elf/dt-relr-2a.d | 10 ++++++++++
> ld/testsuite/ld-elf/dt-relr-2b.d | 17 +++++++++++++++++
> ld/testsuite/ld-elf/dt-relr-2c.d | 17 +++++++++++++++++
> ld/testsuite/ld-elf/dt-relr-2d.d |  9 +++++++++
> ld/testsuite/ld-elf/dt-relr-2e.d |  9 +++++++++
> ld/testsuite/ld-elf/dt-relr-2f.d |  8 ++++++++
> ld/testsuite/ld-elf/dt-relr-2g.d |  9 +++++++++
> ld/testsuite/ld-elf/dt-relr-2h.d |  9 +++++++++
> 13 files changed, 149 insertions(+)
> create mode 100644 ld/testsuite/ld-elf/dt-relr-1.s
> create mode 100644 ld/testsuite/ld-elf/dt-relr-1a.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-1b.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-1c.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2.s
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2a.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2b.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2c.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2d.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2e.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2f.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2g.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2h.d
>
>diff --git a/ld/testsuite/ld-elf/dt-relr-1.s b/ld/testsuite/ld-elf/dt-relr-1.s
>new file mode 100644
>index 00000000000..18486d3acb2
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-1.s
>@@ -0,0 +1,13 @@
>+	.text
>+	.p2align 3
>+	.globl _start
>+_start:
>+	.byte 0
>+
>+	.data
>+	.p2align 3
>+	.globl data
>+data:
>+	.byte 0
>+	//  Offset is not a multiple of 2.  Don't use DT_RELR.
>+	.dc.a __ehdr_start + 10
>diff --git a/ld/testsuite/ld-elf/dt-relr-1a.d b/ld/testsuite/ld-elf/dt-relr-1a.d
>new file mode 100644
>index 00000000000..55c93cefb59
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-1a.d
>@@ -0,0 +1,10 @@
>+#source: dt-relr-1.s
>+#ld: -e _start $DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#...
>+There is no dynamic section in this file.
>+#...
>+There are no relocations in this file.
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-1b.d b/ld/testsuite/ld-elf/dt-relr-1b.d
>new file mode 100644
>index 00000000000..2b78f75d378
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-1b.d
>@@ -0,0 +1,9 @@
>+#source: dt-relr-1.s
>+#ld: -e _start -pie $DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#failif
>+#...
>+Relocation section '\.relr\.dyn' at offset .*

Worth testing "contains XX entries" and "YY offsets".

>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-1c.d b/ld/testsuite/ld-elf/dt-relr-1c.d
>new file mode 100644
>index 00000000000..14f6cda6832
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-1c.d
>@@ -0,0 +1,9 @@
>+#source: dt-relr-1.s
>+#ld: -shared $DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#failif
>+#...
>+Relocation section '\.relr\.dyn' at offset .*

Worth testing "contains XX entries" and "YY offsets".

>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2.s b/ld/testsuite/ld-elf/dt-relr-2.s
>new file mode 100644
>index 00000000000..c3917ee8c3a
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2.s
>@@ -0,0 +1,20 @@
>+	.text
>+	.p2align 3
>+	.globl _start
>+_start:
>+	.byte 0
>+
>+	.data
>+	.p2align 3
>+	.globl data
>+data:
>+
>+	.dc.a .data
>+	.dc.a 0
>+	.dc.a data + 2
>+	.dc.a __ehdr_start + 4
>+	.dc.a __ehdr_start + 9
>+
>+	.byte 0
>+	//  Offset is not a multiple of 2.  Don't use DT_RELR.
>+	.dc.a __ehdr_start + 10
>diff --git a/ld/testsuite/ld-elf/dt-relr-2a.d b/ld/testsuite/ld-elf/dt-relr-2a.d
>new file mode 100644
>index 00000000000..31ef9e8e80e
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2a.d
>@@ -0,0 +1,10 @@
>+#source: dt-relr-2.s
>+#ld: -e _start $DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#...
>+There is no dynamic section in this file.
>+#...
>+There are no relocations in this file.
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2b.d b/ld/testsuite/ld-elf/dt-relr-2b.d
>new file mode 100644
>index 00000000000..7c401732a56
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2b.d
>@@ -0,0 +1,17 @@
>+#source: dt-relr-2.s
>+#ld: -e _start -pie $DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#...
>+ 0x[0-9a-f]+ \(RELR\)    +0x[0-9a-f]+
>+ 0x[0-9a-f]+ \(RELRSZ\)  +(8|16) \(bytes\)
>+ 0x[0-9a-f]+ \(RELRENT\) +(4|8) \(bytes\)
>+#...
>+Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 1 entry:
>+#...
>+[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .*
>+#...
>+Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
>+  4 offsets
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2c.d b/ld/testsuite/ld-elf/dt-relr-2c.d
>new file mode 100644
>index 00000000000..63877b2f90f
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2c.d
>@@ -0,0 +1,17 @@
>+#source: dt-relr-2.s
>+#ld: -shared $DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#...
>+ 0x[0-9a-f]+ \(RELR\)    +0x[0-9a-f]+
>+ 0x[0-9a-f]+ \(RELRSZ\)  +(8|16) \(bytes\)
>+ 0x[0-9a-f]+ \(RELRENT\) +(4|8) \(bytes\)
>+#...
>+Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
>+#...
>+[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .*
>+#...
>+Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
>+  3 offsets
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2d.d b/ld/testsuite/ld-elf/dt-relr-2d.d
>new file mode 100644
>index 00000000000..270a901f1a6
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2d.d
>@@ -0,0 +1,9 @@
>+#source: dt-relr-2.s
>+#ld: -e _start -pie $DT_RELR_LDFLAGS --no-relax
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#failif
>+#...
>+Relocation section '\.relr\.dyn' at offset .*
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2e.d b/ld/testsuite/ld-elf/dt-relr-2e.d
>new file mode 100644
>index 00000000000..79ea62b096a
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2e.d
>@@ -0,0 +1,9 @@
>+#source: dt-relr-2.s
>+#ld: -e _start -pie $DT_RELR_LDFLAGS -z nocombreloc
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#failif
>+#...
>+Relocation section '\.relr\.dyn' at offset .*
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2f.d b/ld/testsuite/ld-elf/dt-relr-2f.d
>new file mode 100644
>index 00000000000..4ad592f71fb
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2f.d
>@@ -0,0 +1,8 @@
>+#source: dt-relr-2.s
>+#ld: -r $DT_RELR_LDFLAGS
>+#readelf: -rW
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#...
>+Relocation section '\.rel(a|)\.data' at offset 0x[0-9a-f]+ contains 5 entries:
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2g.d b/ld/testsuite/ld-elf/dt-relr-2g.d
>new file mode 100644
>index 00000000000..78e370068af
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2g.d
>@@ -0,0 +1,9 @@
>+#source: dt-relr-2.s
>+#ld: -e _start -pie $NO_DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#failif
>+#...
>+Relocation section '\.relr\.dyn' at offset .*
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2h.d b/ld/testsuite/ld-elf/dt-relr-2h.d
>new file mode 100644
>index 00000000000..312373fb179
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2h.d
>@@ -0,0 +1,9 @@
>+#source: dt-relr-2.s
>+#ld: -e _start -shared $NO_DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#failif
>+#...
>+Relocation section '\.relr\.dyn' at offset .*
>+#pass
>-- 
>2.33.1
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 05/10] ld: Initial DT_RELR support
  2022-01-08  2:10   ` Fangrui Song
@ 2022-01-08  2:42     ` H.J. Lu
  2022-01-08 18:32       ` H.J. Lu
  0 siblings, 1 reply; 31+ messages in thread
From: H.J. Lu @ 2022-01-08  2:42 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils, GNU C Library

On Fri, Jan 7, 2022 at 6:10 PM Fangrui Song <i@maskray.me> wrote:
>
> On 2022-01-07, H.J. Lu via Binutils wrote:
> >Add a -z pack-relative-relocs option to enable DT_RELR and create a
> >relr.dyn section for DT_RELR.
> >
> >-z pack-relative-relocs implies -z combreloc and --relax.  --no-relax
> >and -z nocombreloc imply -z nopack-relative-relocs.
> >
> >-z pack-relative-relocs is chosen over the similar option in lld,
> >--pack-dyn-relocs=relr, to implement a glibc binary lockout mechanism
> >with a special glibc version symbol, to avoid random crashes of DT_RELR
> >binaries with the existing glibc binaries.
>
> Why does --no-relax suppress  -z nopack-relative-relocs?

-z nopack-relative-relocs uses the linker relaxation.  It is
possible to do it with --no-relax.  But it requires a major change
in the linker relaxation.

> My mental model is that --relax is for GOTPCRELX/TLS optimization/RISC-V
> relaxation/AArch64 GOT optimization/(hopefully PowerPC64 TOC
> optimization)/etc. It should be orthogonal to RELR. It is true that
> both RISC-V relaxation/RELR need to compute the layouts more than once,
> but other passes technically don't need to be coupled with layout
> computation.

I will look into it after the initial DT_RELR work is checked in.

> People specifying --no-relax may work around potential bugs, but they
> may not want to lose the benefit of RELR.
>
> >bfd/
> >
> >       * elf-bfd.h (elf_link_hash_table): Add srelrdyn.
> >       * elflink.c (_bfd_elf_link_create_dynamic_sections): Create a
> >       .relr.dyn section for DT_RELR.
> >
> >include/
> >
> >       * bfdlink.h (bfd_link_info): Add enable_dt_relr.
> >
> >ld/
> >
> >       * News: Mention -z pack-relative-relocs and
> >       -z nopack-relative-relocs.
> >       * ld.texi: Document -z pack-relative-relocs and
> >       -z nopack-relative-relocs.
> >       * ldelf.c (ldelf_after_parse): Disable DT_RELR if not building
> >       PIE nor shared library.  Add 3 spare dynamic tags for DT_RELR,
> >       DT_RELRSZ and DT_RELRENT.
> >       * lexsup.c (parse_args): Disable DT_RELR for --no-relax.
> >       * emulparams/elf32_x86_64.sh: Source dt-relr.sh.
> >       * emulparams/elf_i386.sh: Likewise.
> >       * emulparams/elf_x86_64.sh: Likewise.
> >       * emulparams/dt-relr.sh: New file.
> >       * emultempl/elf.em (gld${EMULATION_NAME}_handle_option): Disable
> >       DT_RELR for -z nocombreloc.
> >       * scripttempl/elf.sc: Support .relr.dyn.
> >---
> > bfd/elf-bfd.h                 |  1 +
> > bfd/elflink.c                 | 11 +++++++++++
> > include/bfdlink.h             |  4 ++++
> > ld/NEWS                       |  3 +++
> > ld/emulparams/dt-relr.sh      | 21 +++++++++++++++++++++
> > ld/emulparams/elf32_x86_64.sh |  1 +
> > ld/emulparams/elf_i386.sh     |  1 +
> > ld/emulparams/elf_x86_64.sh   |  1 +
> > ld/emultempl/elf.em           |  5 ++++-
> > ld/ld.texi                    | 14 +++++++++++++-
> > ld/ldelf.c                    | 13 +++++++++++++
> > ld/lexsup.c                   |  1 +
> > ld/scripttempl/elf.sc         |  4 ++++
> > 13 files changed, 78 insertions(+), 2 deletions(-)
> > create mode 100644 ld/emulparams/dt-relr.sh
> >
> >diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
> >index c4d2ef00d6b..4e73d79ee77 100644
> >--- a/bfd/elf-bfd.h
> >+++ b/bfd/elf-bfd.h
> >@@ -707,6 +707,7 @@ struct elf_link_hash_table
> >   asection *irelplt;
> >   asection *irelifunc;
> >   asection *dynsym;
> >+  asection *srelrdyn;
> > };
> >
> > /* Returns TRUE if the hash table is a struct elf_link_hash_table.  */
> >diff --git a/bfd/elflink.c b/bfd/elflink.c
> >index bea413ec24e..d51b00b6c10 100644
> >--- a/bfd/elflink.c
> >+++ b/bfd/elflink.c
> >@@ -359,6 +359,17 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
> >       elf_section_data (s)->this_hdr.sh_entsize = 4;
> >     }
> >
> >+  if (info->enable_dt_relr)
> >+    {
> >+      s = bfd_make_section_anyway_with_flags (abfd, ".relr.dyn",
> >+                                            (bed->dynamic_sec_flags
> >+                                             | SEC_READONLY));
> >+      if (s == NULL
> >+        || !bfd_set_section_alignment (s, bed->s->log_file_align))
> >+      return false;
> >+      elf_hash_table (info)->srelrdyn = s;
> >+    }
> >+
> >   /* Let the backend create the rest of the sections.  This lets the
> >      backend set the right flags.  The backend will normally create
> >      the .got and .plt sections.  */
> >diff --git a/include/bfdlink.h b/include/bfdlink.h
> >index 01f57c22edf..92e3e32360b 100644
> >--- a/include/bfdlink.h
> >+++ b/include/bfdlink.h
> >@@ -413,6 +413,10 @@ struct bfd_link_info
> >   /* TRUE if PT_GNU_RELRO segment should be created.  */
> >   unsigned int relro: 1;
> >
> >+  /* TRUE if DT_RELR should be enabled for compact relative
> >+     relocations.  */
> >+  unsigned int enable_dt_relr: 1;
> >+
> >   /* TRUE if separate code segment should be created.  */
> >   unsigned int separate_code: 1;
> >
> >diff --git a/ld/NEWS b/ld/NEWS
> >index 5d3d80dbbba..77c716b577d 100644
> >--- a/ld/NEWS
> >+++ b/ld/NEWS
> >@@ -1,5 +1,8 @@
> > -*- text -*-
> >
> >+* Add -z pack-relative-relocs/-z no pack-relative-relocs to x86 ELF
> >+  linker to pack relative relocations in the DT_RELR section.
> >+
> > * Add support for the LoongArch architecture.
> >
> > * Add -z indirect-extern-access/-z noindirect-extern-access to x86 ELF
> >diff --git a/ld/emulparams/dt-relr.sh b/ld/emulparams/dt-relr.sh
> >new file mode 100644
> >index 00000000000..ed93ee2b5c2
> >--- /dev/null
> >+++ b/ld/emulparams/dt-relr.sh
> >@@ -0,0 +1,21 @@
> >+HAVE_DT_RELR=yes
> >+PARSE_AND_LIST_OPTIONS_PACK_RELATIVE_RELOCS='
> >+  fprintf (file, _("\
> >+  -z pack-relative-relocs     Pack relative relocations\n"));
> >+  fprintf (file, _("\
> >+  -z nopack-relative-relocs   Do not pack relative relocations (default)\n"));
> >+'
> >+
> >+PARSE_AND_LIST_ARGS_CASE_Z_PACK_RELATIVE_RELOCS='
> >+      else if (strcmp (optarg, "pack-relative-relocs") == 0)
> >+      {
> >+        link_info.enable_dt_relr = true;
> >+        link_info.combreloc = true;
> >+      }
> >+      else if (strcmp (optarg, "nopack-relative-relocs") == 0)
> >+      link_info.enable_dt_relr = false;
> >+'
> >+
> >+
> >+PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_PACK_RELATIVE_RELOCS"
> >+PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_PACK_RELATIVE_RELOCS"
> >diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh
> >index ac0a7aa6dcf..4bff41287c1 100644
> >--- a/ld/emulparams/elf32_x86_64.sh
> >+++ b/ld/emulparams/elf32_x86_64.sh
> >@@ -7,6 +7,7 @@ source_sh ${srcdir}/emulparams/cet.sh
> > source_sh ${srcdir}/emulparams/x86-report-relative.sh
> > source_sh ${srcdir}/emulparams/x86-64-level.sh
> > source_sh ${srcdir}/emulparams/static.sh
> >+source_sh ${srcdir}/emulparams/dt-relr.sh
> > SCRIPT_NAME=elf
> > ELFSIZE=32
> > OUTPUT_FORMAT="elf32-x86-64"
> >diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh
> >index 98532e5edbc..ae17bb4b3f7 100644
> >--- a/ld/emulparams/elf_i386.sh
> >+++ b/ld/emulparams/elf_i386.sh
> >@@ -6,6 +6,7 @@ source_sh ${srcdir}/emulparams/cet.sh
> > source_sh ${srcdir}/emulparams/x86-report-relative.sh
> > source_sh ${srcdir}/emulparams/x86-64-level.sh
> > source_sh ${srcdir}/emulparams/static.sh
> >+source_sh ${srcdir}/emulparams/dt-relr.sh
> > SCRIPT_NAME=elf
> > OUTPUT_FORMAT="elf32-i386"
> > NO_RELA_RELOCS=yes
> >diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh
> >index 48d0974711b..5f2743ed409 100644
> >--- a/ld/emulparams/elf_x86_64.sh
> >+++ b/ld/emulparams/elf_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-lam.sh
> > source_sh ${srcdir}/emulparams/static.sh
> >+source_sh ${srcdir}/emulparams/dt-relr.sh
> > SCRIPT_NAME=elf
> > ELFSIZE=64
> > OUTPUT_FORMAT="elf64-x86-64"
> >diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em
> >index 59775260b06..7a32a4cc4d4 100644
> >--- a/ld/emultempl/elf.em
> >+++ b/ld/emultempl/elf.em
> >@@ -822,7 +822,10 @@ fragment <<EOF
> >       else if (strcmp (optarg, "combreloc") == 0)
> >       link_info.combreloc = true;
> >       else if (strcmp (optarg, "nocombreloc") == 0)
> >-      link_info.combreloc = false;
> >+      {
> >+        link_info.combreloc = false;
> >+        link_info.enable_dt_relr = false;
> >+      }
> >       else if (strcmp (optarg, "nocopyreloc") == 0)
> >       link_info.nocopyreloc = true;
> > EOF
> >diff --git a/ld/ld.texi b/ld/ld.texi
> >index edcf1772855..457089ec06a 100644
> >--- a/ld/ld.texi
> >+++ b/ld/ld.texi
> >@@ -1242,6 +1242,7 @@ Supported for Linux/i386 and Linux/x86_64.
> > @itemx nocombreloc
> > Combine multiple dynamic relocation sections and sort to improve
> > dynamic symbol lookup caching.  Do not do this if @samp{nocombreloc}.
> >+@samp{nocombreloc} implies @samp{nopack-relative-relocs}.
> >
> > @item common
> > @itemx nocommon
> >@@ -1430,6 +1431,16 @@ called.
> > @item origin
> > Specify that the object requires @samp{$ORIGIN} handling in paths.
> >
> >+@item pack-relative-relocs
> >+@itemx nopack-relative-relocs
> >+Generate compact relative relocation in position-independent executable
> >+and shared library.  It adds @code{DT_RELR}, @code{DT_RELRSZ} and
> >+@code{DT_RELRENT} entries to the dynamic section.  It is ignored when
> >+building position-dependent executable and relocatable output.  This
> >+option also implies @option{combreloc} and @option{--relax}.
> >+@option{nopack-relative-relocs} is the default, which disables
> >+compact relative relocation.  Supported for i386 and x86-64.
> >+
> > @item relro
> > @itemx norelro
> > Create an ELF @code{PT_GNU_RELRO} segment header in the object.  This
> >@@ -2215,7 +2226,8 @@ family of processors.
> > @end ifset
> >
> > On platforms where the feature is supported, the option
> >-@option{--no-relax} will disable it.
> >+@option{--no-relax} will disable it and also imply
> >+@option{-z nopack-relative-relocs}.
> >
> > On platforms where the feature is not supported, both @option{--relax}
> > and @option{--no-relax} are accepted, but ignored.
> >diff --git a/ld/ldelf.c b/ld/ldelf.c
> >index d15f027e91a..1978ac477f5 100644
> >--- a/ld/ldelf.c
> >+++ b/ld/ldelf.c
> >@@ -71,6 +71,19 @@ ldelf_after_parse (void)
> >       einfo (_("%P: warning: -z dynamic-undefined-weak ignored\n"));
> >       link_info.dynamic_undefined_weak = 0;
> >     }
> >+
> >+  /* Disable DT_RELR if not building PIE nor shared library.  */
> >+  if (!bfd_link_pic (&link_info))
> >+    link_info.enable_dt_relr = 0;
> >+
> >+  if (link_info.enable_dt_relr)
> >+    {
> >+      ENABLE_RELAXATION;
> >+
> >+      /* Add 3 spare tags for DT_RELR, DT_RELRSZ and DT_RELRENT.  */
> >+      link_info.spare_dynamic_tags += 3;
> >+    }
> >+
> >   after_parse_default ();
> >   if (link_info.commonpagesize > link_info.maxpagesize)
> >     einfo (_("%F%P: common page size (0x%v) > maximum page size (0x%v)\n"),
> >diff --git a/ld/lexsup.c b/ld/lexsup.c
> >index 5acc47ed5a0..3942716963a 100644
> >--- a/ld/lexsup.c
> >+++ b/ld/lexsup.c
> >@@ -1229,6 +1229,7 @@ parse_args (unsigned argc, char **argv)
> >         break;
> >       case OPTION_NO_RELAX:
> >         DISABLE_RELAXATION;
> >+        link_info.enable_dt_relr = false;
> >         break;
> >       case OPTION_RELAX:
> >         ENABLE_RELAXATION;
> >diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
> >index a9a39ad402c..f3552a4a554 100644
> >--- a/ld/scripttempl/elf.sc
> >+++ b/ld/scripttempl/elf.sc
> >@@ -10,6 +10,7 @@
> > #             empty.
> > #     HAVE_NOINIT - Include a .noinit output section in the script.
> > #     HAVE_PERSISTENT - Include a .persistent output section in the script.
> >+#     HAVE_DT_RELR - Include a .relr.dyn output section in the script.
> > #     SMALL_DATA_CTOR - .ctors contains small data.
> > #     SMALL_DATA_DTOR - .dtors contains small data.
> > #     DATA_ADDR - if end-of-text-plus-one-page isn't right for data start
> >@@ -520,6 +521,9 @@ emit_dyn()
> >     fi
> >   fi
> >   rm -f ldscripts/dyntmp.$$
> >+  if test -n "${COMBRELOC}" && test -n "${HAVE_DT_RELR}"; then
> >+    echo "  .relr.dyn : { *(.relr.dyn) }"
> >+  fi
> > }
> >
> > test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn
> >--
> >2.33.1
> >



-- 
H.J.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 07/10] elf: Support DT_RELR in linker tests
  2022-01-07 19:06 ` [PATCH 07/10] elf: Support DT_RELR in linker tests H.J. Lu
@ 2022-01-08  2:42   ` Fangrui Song
  2022-01-08 13:46     ` H.J. Lu
  0 siblings, 1 reply; 31+ messages in thread
From: Fangrui Song @ 2022-01-08  2:42 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, libc-alpha


On 2022-01-07, H.J. Lu via Binutils wrote:
>Allow eabling and disabling DT_RELR in linker tests.  Disable DT_RELR in
>linker tests which don't expect DT_RELR in linker outputs.
>
>binutils/
>
>	* testsuite/lib/binutils-common.exp (run_dump_test): Make
>	DT_RELR_LDFLAGS and NO_DT_RELR_LDFLAGS global.
>
>ld/
>
>	* testsuite/config/default.exp (DT_RELR_LDFLAGS): New.
>	(DT_RELR_CC_LDFLAGS): Likewise.
>	(NO_DT_RELR_LDFLAGS): Likewise.
>	(NO_DT_RELR_CC_LDFLAGS): Likewise.
>	* testsuite/ld-elf/shared.exp: Pass $NO_DT_RELR_LDFLAGS to
>	linker for some tests.
>	* testsuite/ld-i386/export-class.exp: Likewise.
>	* testsuite/ld-i386/i386.exp: Likewise.
>	* testsuite/ld-i386/ibt-plt-2a.d: Pass $NO_DT_RELR_LDFLAGS to
>	linker.
>	* testsuite/ld-i386/ibt-plt-3a.d: Likewise.
>	* testsuite/ld-i386/ibt-plt-3c.d: Likewise.
>	* testsuite/ld-i386/report-reloc-1.d: Likewise.
>	* testsuite/ld-ifunc/ifunc-2-i386-now.d: Likewise.
>	* testsuite/ld-ifunc/ifunc-2-local-i386-now.d: Likewise.
>	* testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d: Likewise.
>	* testsuite/ld-ifunc/ifunc-2-x86-64-now.d: Likewise.
>	* testsuite/ld-ifunc/pr17154-x86-64.d: Likewise.
>	* testsuite/ld-x86-64/bnd-branch-1-now.d: Likewise.
>	* testsuite/ld-x86-64/bnd-ifunc-1-now.d: Likewise.
>	* testsuite/ld-x86-64/bnd-ifunc-2-now.d: Likewise.
>	* testsuite/ld-x86-64/bnd-ifunc-2.d: Likewise.
>	* testsuite/ld-x86-64/bnd-plt-1-now.d: Likewise.
>	* testsuite/ld-x86-64/bnd-plt-1.d: Likewise.
>	* testsuite/ld-x86-64/ibt-plt-2a-x32.d: Likewise.
>	* testsuite/ld-x86-64/ibt-plt-2a.d: Likewise.
>	* testsuite/ld-x86-64/ibt-plt-3a-x32.d: Likewise.
>	* testsuite/ld-x86-64/ibt-plt-3a.d: Likewise.
>	* testsuite/ld-x86-64/ilp32-4.d: Likewise.
>	* testsuite/ld-x86-64/load1c.d: Likewise.
>	* testsuite/ld-x86-64/load1d.d: Likewise.
>	* testsuite/ld-x86-64/pr13082-2b.d: Likewise.
>	* testsuite/ld-x86-64/pr14207.d: Likewise.
>	* testsuite/ld-x86-64/pr18176.d: Likewise.
>	* testsuite/ld-x86-64/pr19162.d: Likewise.
>	* testsuite/ld-x86-64/pr19636-2d.d: Likewise.
>	* testsuite/ld-x86-64/pr19636-2l.d: Likewise.
>	* testsuite/ld-x86-64/pr20253-1d.d: Likewise.
>	* testsuite/ld-x86-64/pr20253-1f.d: Likewise.
>	* testsuite/ld-x86-64/pr20253-1j.d: Likewise.
>	* testsuite/ld-x86-64/pr20253-1l.d: Likewise.
>	* testsuite/ld-x86-64/report-reloc-1-x32.d: Likewise.
>	* testsuite/ld-x86-64/report-reloc-1.d: Likewise.
>	* testsuite/ld-x86-64/export-class.exp (x86_64_export_class_test):
>	Pass $NO_DT_RELR_LDFLAGS to linker.
>	* testsuite/ld-x86-64/x86-64.exp: Pass $NO_DT_RELR_LDFLAGS to
>	linker for some tests.
>---
> binutils/testsuite/lib/binutils-common.exp    |  1 +
> ld/testsuite/config/default.exp               | 16 +++++
> ld/testsuite/ld-elf/shared.exp                |  3 +-
> ld/testsuite/ld-i386/export-class.exp         |  2 +-
> ld/testsuite/ld-i386/i386.exp                 | 20 ++++--
> ld/testsuite/ld-i386/ibt-plt-2a.d             |  2 +-
> ld/testsuite/ld-i386/ibt-plt-3a.d             |  2 +-
> ld/testsuite/ld-i386/ibt-plt-3c.d             |  2 +-
> ld/testsuite/ld-i386/report-reloc-1.d         |  2 +-
> ld/testsuite/ld-ifunc/ifunc-2-i386-now.d      |  2 +-
> .../ld-ifunc/ifunc-2-local-i386-now.d         |  2 +-
> .../ld-ifunc/ifunc-2-local-x86-64-now.d       |  2 +-
> ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d    |  2 +-
> ld/testsuite/ld-ifunc/pr17154-x86-64-now.d    |  2 +-
> ld/testsuite/ld-ifunc/pr17154-x86-64.d        |  2 +-
> ld/testsuite/ld-x86-64/bnd-branch-1-now.d     |  2 +-
> ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d      |  2 +-
> ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d      |  2 +-
> ld/testsuite/ld-x86-64/bnd-ifunc-2.d          |  2 +-
> ld/testsuite/ld-x86-64/bnd-plt-1-now.d        |  2 +-
> ld/testsuite/ld-x86-64/bnd-plt-1.d            |  2 +-
> ld/testsuite/ld-x86-64/export-class.exp       |  3 +-
> ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d       |  2 +-
> ld/testsuite/ld-x86-64/ibt-plt-2a.d           |  2 +-
> ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d       |  2 +-
> ld/testsuite/ld-x86-64/ibt-plt-3a.d           |  2 +-
> ld/testsuite/ld-x86-64/ilp32-4.d              |  2 +-
> ld/testsuite/ld-x86-64/load1c.d               |  2 +-
> ld/testsuite/ld-x86-64/load1d.d               |  2 +-
> ld/testsuite/ld-x86-64/pr13082-2b.d           |  2 +-
> ld/testsuite/ld-x86-64/pr14207.d              |  2 +-
> ld/testsuite/ld-x86-64/pr18176.d              |  2 +-
> ld/testsuite/ld-x86-64/pr19162.d              |  2 +-
> ld/testsuite/ld-x86-64/pr19636-2d.d           |  2 +-
> ld/testsuite/ld-x86-64/pr19636-2l.d           |  2 +-
> ld/testsuite/ld-x86-64/pr20253-1d.d           |  2 +-
> ld/testsuite/ld-x86-64/pr20253-1f.d           |  2 +-
> ld/testsuite/ld-x86-64/pr20253-1j.d           |  2 +-
> ld/testsuite/ld-x86-64/pr20253-1l.d           |  2 +-
> ld/testsuite/ld-x86-64/report-reloc-1-x32.d   |  2 +-
> ld/testsuite/ld-x86-64/report-reloc-1.d       |  2 +-
> ld/testsuite/ld-x86-64/x86-64.exp             | 65 ++++++++++++-------
> 42 files changed, 114 insertions(+), 66 deletions(-)
>
>diff --git a/binutils/testsuite/lib/binutils-common.exp b/binutils/testsuite/lib/binutils-common.exp
>index 0e0ba8e5aee..88fdc1a71c7 100644
>--- a/binutils/testsuite/lib/binutils-common.exp
>+++ b/binutils/testsuite/lib/binutils-common.exp
>@@ -855,6 +855,7 @@ proc run_dump_test { name {extra_options {}} } {
>     global ELFEDIT ELFEDITFLAGS LD LDFLAGS NM NMFLAGS OBJCOPY OBJCOPYFLAGS
>     global OBJDUMP OBJDUMPFLAGS READELF READELFFLAGS STRIP STRIPFLAGS
>     global copyfile env runtests srcdir subdir verbose
>+    global DT_RELR_LDFLAGS NO_DT_RELR_LDFLAGS
>
>     if [string match "*/*" $name] {
> 	set file $name
>diff --git a/ld/testsuite/config/default.exp b/ld/testsuite/config/default.exp
>index c988d5d2924..52e75048ede 100644
>--- a/ld/testsuite/config/default.exp
>+++ b/ld/testsuite/config/default.exp
>@@ -313,6 +313,22 @@ if ![info exists LDFLAGS] then {
>     set LDFLAGS {}
> }
>
>+if { ![info exists DT_RELR_LDFLAGS] } then {
>+    set DT_RELR_LDFLAGS "-z pack-relative-relocs"
>+}

>+if { ![info exists DT_RELR_CC_LDFLAGS] } then {
>+    set DT_RELR_CC_LDFLAGS "-Wl,-z,pack-relative-relocs"
>+}
>+

GCC driver supports -z for a very long time (at least >=4.1.2),
so -Wl,-z, may be combined with the preceding -z.

>+if { ![info exists NO_DT_RELR_LDFLAGS] } then {
>+    set NO_DT_RELR_LDFLAGS "-z nopack-relative-relocs"
>+}
>+
>+if { ![info exists NO_DT_RELR_CC_LDFLAGS] } then {
>+    set NO_DT_RELR_CC_LDFLAGS "-Wl,-z,nopack-relative-relocs"
>+}
>+
> # Set LD_CLASS to "64bit" for a 64-bit *host* linker.
> if { ![info exists LD_CLASS] } then {
>     set REAL_LD [findfile $base_dir/.libs/ld-new .libs/ld-new $LD [transform ld]]
>diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
>index cb3b8c15cfc..1381544e6f8 100644
>--- a/ld/testsuite/ld-elf/shared.exp
>+++ b/ld/testsuite/ld-elf/shared.exp
>@@ -452,7 +452,8 @@ setup_xfail mips*-*-* bfin-*-*
> clear_xfail bfin-*-linux*
> run_ld_link_tests [list \
>     [list "-Bsymbolic-functions" \
>-	"-shared -Bsymbolic-functions" "" "$AFLAGS_PIC" \
>+	"-shared -Bsymbolic-functions $NO_DT_RELR_LDFLAGS" \
>+	"" "$AFLAGS_PIC" \
> 	{symbolic-func.s} {{readelf {-r --wide} symbolic-func.r}} \
> 	"symbolic-func.so"] \
> ]
>diff --git a/ld/testsuite/ld-i386/export-class.exp b/ld/testsuite/ld-i386/export-class.exp
>index 47b2c0f0056..04bc6a0d836 100644
>--- a/ld/testsuite/ld-i386/export-class.exp
>+++ b/ld/testsuite/ld-i386/export-class.exp
>@@ -74,7 +74,7 @@ run_ld_link_tests [list \
> run_ld_link_tests [list \
>     [list \
> 	"$testname (final shared object)" \
>-	"-shared -Tdata=0x12340000 tmpdir/i386-export-class-ref-r.o tmpdir/i386-export-class-lib.so" "" \
>+	"-shared $NO_DT_RELR_LDFLAGS -Tdata=0x12340000 tmpdir/i386-export-class-ref-r.o tmpdir/i386-export-class-lib.so" "" \
> 	"" \
> 	{ ../ld-elf/export-class-dep.s ../ld-elf/export-class-def.s } \
> 	{ \
>diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
>index 3ed6e42e78f..c2d8d8268c3 100644
>--- a/ld/testsuite/ld-i386/i386.exp
>+++ b/ld/testsuite/ld-i386/i386.exp
>@@ -177,12 +177,6 @@ set i386tests {
>      {{readelf -Ssrl tlsbindesc.rd} {objdump -drj.text tlsbindesc.dd}
>       {objdump -sj.got tlsbindesc.sd} {objdump -sj.tdata tlsbindesc.td}}
>       "tlsbindesc"}
>-    {"TLS -fno-pic -shared"
>-     "-shared -melf_i386 --no-ld-generated-unwind-info -z notext \
>-      -z noseparate-code --hash-style=sysv" ""
>-     "--32" {tlsnopic1.s tlsnopic2.s}
>-     {{readelf -Ssrl tlsnopic.rd} {objdump -drj.text tlsnopic.dd}
>-      {objdump -sj.got tlsnopic.sd}} "libtlsnopic.so"}
>     {"TLS with global dynamic and descriptors"
>      "-shared -melf_i386 --no-ld-generated-unwind-info \
>       -z noseparate-code --hash-style=sysv" ""
>@@ -293,6 +287,20 @@ iamcu_tests
>
> run_ld_link_tests $i386tests
>
>+run_ld_link_tests [list \
>+    [list \
>+	"TLS -fno-pic -shared" \
>+	"-shared -melf_i386 --no-ld-generated-unwind-info -z notext \
>+	 -z noseparate-code --hash-style=sysv $NO_DT_RELR_LDFLAGS" \
>+	"" "--32" \
>+	{tlsnopic1.s tlsnopic2.s} \
>+	{{readelf -Ssrl tlsnopic.rd} \
>+	 {objdump -drj.text tlsnopic.dd} \
>+	 {objdump -sj.got tlsnopic.sd}} \
>+	"libtlsnopic.so" \
>+    ] \
>+]
>+
> run_dump_test "abs"
> run_dump_test "pcrel8"
> run_dump_test "pcrel16"
>diff --git a/ld/testsuite/ld-i386/ibt-plt-2a.d b/ld/testsuite/ld-i386/ibt-plt-2a.d
>index 42aa2ce7410..98b6fb9a5aa 100644
>--- a/ld/testsuite/ld-i386/ibt-plt-2a.d
>+++ b/ld/testsuite/ld-i386/ibt-plt-2a.d
>@@ -1,6 +1,6 @@
> #source: ibt-plt-2.s
> #as: --32
>-#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code
>+#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-i386/ibt-plt-3a.d b/ld/testsuite/ld-i386/ibt-plt-3a.d
>index b357a74a33b..91f2023db35 100644
>--- a/ld/testsuite/ld-i386/ibt-plt-3a.d
>+++ b/ld/testsuite/ld-i386/ibt-plt-3a.d
>@@ -1,6 +1,6 @@
> #source: ibt-plt-3.s
> #as: --32
>-#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code
>+#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-i386/ibt-plt-3c.d b/ld/testsuite/ld-i386/ibt-plt-3c.d
>index b357a74a33b..91f2023db35 100644
>--- a/ld/testsuite/ld-i386/ibt-plt-3c.d
>+++ b/ld/testsuite/ld-i386/ibt-plt-3c.d
>@@ -1,6 +1,6 @@
> #source: ibt-plt-3.s
> #as: --32
>-#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code
>+#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-i386/report-reloc-1.d b/ld/testsuite/ld-i386/report-reloc-1.d
>index 51fbbd8d105..162161592a1 100644
>--- a/ld/testsuite/ld-i386/report-reloc-1.d
>+++ b/ld/testsuite/ld-i386/report-reloc-1.d
>@@ -1,6 +1,6 @@
> #source: report-reloc-1.s
> #as: --32
>-#ld: -pie -melf_i386 -z report-relative-reloc
>+#ld: -pie -melf_i386 -z report-relative-reloc $NO_DT_RELR_LDFLAGS
> #warning_output: report-reloc-1.l
> #readelf: -r --wide
>
>diff --git a/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d b/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d
>index 0d3f7b80d06..aae24b2809d 100644
>--- a/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d
>+++ b/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d
>@@ -1,5 +1,5 @@
> #source: ifunc-2-i386.s
>-#ld: -z now -m elf_i386 -shared --hash-style=sysv -z noseparate-code
>+#ld: -z now -m elf_i386 -shared --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
> #as: --32
> #objdump: -dw
> #target: x86_64-*-* i?86-*-*
>diff --git a/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d b/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d
>index 48d2084d38f..86083c12a08 100644
>--- a/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d
>+++ b/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d
>@@ -1,5 +1,5 @@
> #source: ifunc-2-local-i386.s
>-#ld: -z now -m elf_i386 -shared --hash-style=sysv -z noseparate-code
>+#ld: -z now -m elf_i386 -shared --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
> #as: --32
> #objdump: -dw
> #target: x86_64-*-* i?86-*-*
>diff --git a/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d b/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d
>index 14866a8f6cc..be3da08e12b 100644
>--- a/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d
>+++ b/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d
>@@ -1,6 +1,6 @@
> #source: ifunc-2-local-x86-64.s
> #as: --64
>-#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
> #target: x86_64-*-*
>
>diff --git a/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d b/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d
>index 1cd60941ac0..b504f9adedd 100644
>--- a/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d
>+++ b/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d
>@@ -1,6 +1,6 @@
> #source: ifunc-2-x86-64.s
> #as: --64
>-#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
> #target: x86_64-*-*
>
>diff --git a/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d b/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d
>index 4cc1dc206d5..f6920272b63 100644
>--- a/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d
>+++ b/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d
>@@ -1,6 +1,6 @@
> #source: pr17154-x86.s
> #as: --64
>-#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
> #target: x86_64-*-*
>
>diff --git a/ld/testsuite/ld-ifunc/pr17154-x86-64.d b/ld/testsuite/ld-ifunc/pr17154-x86-64.d
>index 9fb23d410e3..90918426ee5 100644
>--- a/ld/testsuite/ld-ifunc/pr17154-x86-64.d
>+++ b/ld/testsuite/ld-ifunc/pr17154-x86-64.d
>@@ -1,6 +1,6 @@
> #source: pr17154-x86.s
> #as: --64
>-#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
> #target: x86_64-*-*
>
>diff --git a/ld/testsuite/ld-x86-64/bnd-branch-1-now.d b/ld/testsuite/ld-x86-64/bnd-branch-1-now.d
>index b7bc4e526cc..b1bcea3cf4c 100644
>--- a/ld/testsuite/ld-x86-64/bnd-branch-1-now.d
>+++ b/ld/testsuite/ld-x86-64/bnd-branch-1-now.d
>@@ -1,6 +1,6 @@
> #source: bnd-branch-1.s -mx86-used-note=no
> #as: --64
>-#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d b/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d
>index 15ecfe1cc50..86ba30a46d5 100644
>--- a/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d
>+++ b/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d
>@@ -1,6 +1,6 @@
> #source: bnd-ifunc-1.s
> #as: --64 -madd-bnd-prefix -mx86-used-note=no
>-#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d b/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d
>index 211d72d2335..fa7ec07aaf0 100644
>--- a/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d
>+++ b/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d
>@@ -1,6 +1,6 @@
> #source: bnd-ifunc-2.s
> #as: --64 -madd-bnd-prefix -mx86-used-note=no
>-#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/bnd-ifunc-2.d b/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
>index f80ba15aa35..36534b14feb 100644
>--- a/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
>+++ b/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
>@@ -1,5 +1,5 @@
> #as: --64 -madd-bnd-prefix -mx86-used-note=no
>-#ld: -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> #...
>diff --git a/ld/testsuite/ld-x86-64/bnd-plt-1-now.d b/ld/testsuite/ld-x86-64/bnd-plt-1-now.d
>index 24e28210a0a..47289a04f43 100644
>--- a/ld/testsuite/ld-x86-64/bnd-plt-1-now.d
>+++ b/ld/testsuite/ld-x86-64/bnd-plt-1-now.d
>@@ -1,6 +1,6 @@
> #source: bnd-branch-1.s
> #as: --64 -mx86-used-note=no
>-#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/bnd-plt-1.d b/ld/testsuite/ld-x86-64/bnd-plt-1.d
>index 0df32555c18..f047da897ce 100644
>--- a/ld/testsuite/ld-x86-64/bnd-plt-1.d
>+++ b/ld/testsuite/ld-x86-64/bnd-plt-1.d
>@@ -1,6 +1,6 @@
> #source: bnd-branch-1.s
> #as: --64 -mx86-used-note=no
>-#ld: -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/export-class.exp b/ld/testsuite/ld-x86-64/export-class.exp
>index 26896d1ca87..14c2d240fac 100644
>--- a/ld/testsuite/ld-x86-64/export-class.exp
>+++ b/ld/testsuite/ld-x86-64/export-class.exp
>@@ -31,6 +31,7 @@ if { ![istarget x86_64*-*-linux*] } {
> }
>
> proc x86_64_export_class_test { abi flag emul } {
>+    global NO_DT_RELR_LDFLAGS
>
>     set testname "x86-64 $abi symbol export class test"
>
>@@ -75,7 +76,7 @@ proc x86_64_export_class_test { abi flag emul } {
>     run_ld_link_tests [list \
> 	[list \
> 	    "$testname (final shared object)" \
>-	    "$LDFLAGS -shared -Tdata=0x12340000 tmpdir/x86-64-$abi-export-class-ref-r.o tmpdir/x86-64-$abi-export-class-lib.so" "" \
>+	    "$LDFLAGS $NO_DT_RELR_LDFLAGS -shared -Tdata=0x12340000 tmpdir/x86-64-$abi-export-class-ref-r.o tmpdir/x86-64-$abi-export-class-lib.so" "" \
> 	    "$AFLAGS" \
> 	    { ../ld-elf/export-class-dep.s ../ld-elf/export-class-def.s } \
> 	    [list \
>diff --git a/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d
>index a19cece98e8..23e31e62f55 100644
>--- a/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d
>+++ b/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d
>@@ -1,6 +1,6 @@
> #source: ibt-plt-2.s
> #as: --x32
>-#ld: -shared -m elf32_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -shared -m elf32_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/ibt-plt-2a.d b/ld/testsuite/ld-x86-64/ibt-plt-2a.d
>index 92785929092..adbbf62e84d 100644
>--- a/ld/testsuite/ld-x86-64/ibt-plt-2a.d
>+++ b/ld/testsuite/ld-x86-64/ibt-plt-2a.d
>@@ -1,6 +1,6 @@
> #source: ibt-plt-2.s
> #as: --64 -defsym __64_bit__=1
>-#ld: -shared -m elf_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -shared -m elf_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d
>index d6f8bb3afbe..f52b1cc796f 100644
>--- a/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d
>+++ b/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d
>@@ -1,6 +1,6 @@
> #source: ibt-plt-3.s
> #as: --x32
>-#ld: -shared -m elf32_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -shared -m elf32_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/ibt-plt-3a.d b/ld/testsuite/ld-x86-64/ibt-plt-3a.d
>index 9c15ed4f928..8bd8851ea73 100644
>--- a/ld/testsuite/ld-x86-64/ibt-plt-3a.d
>+++ b/ld/testsuite/ld-x86-64/ibt-plt-3a.d
>@@ -1,6 +1,6 @@
> #source: ibt-plt-3.s
> #as: --64 -defsym __64_bit__=1
>-#ld: -shared -m elf_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -shared -m elf_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/ilp32-4.d b/ld/testsuite/ld-x86-64/ilp32-4.d
>index 34be012056e..ad5c9cdf858 100644
>--- a/ld/testsuite/ld-x86-64/ilp32-4.d
>+++ b/ld/testsuite/ld-x86-64/ilp32-4.d
>@@ -1,5 +1,5 @@
> #as: --x32
>-#ld: -m elf32_x86_64 -shared --no-ld-generated-unwind-info --hash-style=sysv
>+#ld: -m elf32_x86_64 -shared --no-ld-generated-unwind-info --hash-style=sysv $NO_DT_RELR_LDFLAGS
> #readelf: -d -S --wide
> #target: x86_64-*-linux*
>
>diff --git a/ld/testsuite/ld-x86-64/load1c.d b/ld/testsuite/ld-x86-64/load1c.d
>index db9c69fadbf..7404c7093b4 100644
>--- a/ld/testsuite/ld-x86-64/load1c.d
>+++ b/ld/testsuite/ld-x86-64/load1c.d
>@@ -1,6 +1,6 @@
> #source: load1.s
> #as: --64
>-#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/load1d.d b/ld/testsuite/ld-x86-64/load1d.d
>index 7ccae532f27..1b474a375c7 100644
>--- a/ld/testsuite/ld-x86-64/load1d.d
>+++ b/ld/testsuite/ld-x86-64/load1d.d
>@@ -1,6 +1,6 @@
> #source: load1.s
> #as: --x32
>-#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/pr13082-2b.d b/ld/testsuite/ld-x86-64/pr13082-2b.d
>index c218eafe34c..71c44fc0ee5 100644
>--- a/ld/testsuite/ld-x86-64/pr13082-2b.d
>+++ b/ld/testsuite/ld-x86-64/pr13082-2b.d
>@@ -1,7 +1,7 @@
> #source: pr13082-2.s
> #name: PR ld/13082-2 (b)
> #as: --x32
>-#ld: -pie -melf32_x86_64
>+#ld: -pie -melf32_x86_64 $NO_DT_RELR_LDFLAGS
> #readelf: -r --wide
>
> Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entry:
>diff --git a/ld/testsuite/ld-x86-64/pr14207.d b/ld/testsuite/ld-x86-64/pr14207.d
>index f330600b916..e3af36146c6 100644
>--- a/ld/testsuite/ld-x86-64/pr14207.d
>+++ b/ld/testsuite/ld-x86-64/pr14207.d
>@@ -1,6 +1,6 @@
> #name: PR ld/14207
> #as: --64
>-#ld: -melf_x86_64 -shared -z relro -z now --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -melf_x86_64 -shared -z relro -z now --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #readelf: -l --wide
> #target: x86_64-*-linux*
>
>diff --git a/ld/testsuite/ld-x86-64/pr18176.d b/ld/testsuite/ld-x86-64/pr18176.d
>index 4e3ad9ff08d..a99ff15ac6b 100644
>--- a/ld/testsuite/ld-x86-64/pr18176.d
>+++ b/ld/testsuite/ld-x86-64/pr18176.d
>@@ -1,6 +1,6 @@
> #name: PR ld/18176
> #as: --64
>-#ld: -melf_x86_64 -shared -z relro -T pr18176.t -z max-page-size=0x200000 -z common-page-size=0x1000
>+#ld: -melf_x86_64 -shared -z relro -T pr18176.t -z max-page-size=0x200000 -z common-page-size=0x1000 $NO_DT_RELR_LDFLAGS
> #readelf: -l --wide
> #target: x86_64-*-linux*
>
>diff --git a/ld/testsuite/ld-x86-64/pr19162.d b/ld/testsuite/ld-x86-64/pr19162.d
>index 2d51dabe729..f458853d8e5 100644
>--- a/ld/testsuite/ld-x86-64/pr19162.d
>+++ b/ld/testsuite/ld-x86-64/pr19162.d
>@@ -1,7 +1,7 @@
> #source: pr19162a.s
> #source: pr19162b.s
> #as: --64
>-#ld: -melf_x86_64 -shared -z noseparate-code -z max-page-size=0x200000 -z common-page-size=0x1000 --hash-style=sysv
>+#ld: -melf_x86_64 -shared -z noseparate-code -z max-page-size=0x200000 -z common-page-size=0x1000 --hash-style=sysv $NO_DT_RELR_LDFLAGS
> #readelf: -l --wide
> #target: x86_64-*-linux*
>
>diff --git a/ld/testsuite/ld-x86-64/pr19636-2d.d b/ld/testsuite/ld-x86-64/pr19636-2d.d
>index 3bd33a9a915..092992be9d4 100644
>--- a/ld/testsuite/ld-x86-64/pr19636-2d.d
>+++ b/ld/testsuite/ld-x86-64/pr19636-2d.d
>@@ -1,6 +1,6 @@
> #source: pr19636-2.s
> #as: --64 -mrelax-relocations=no
>-#ld: -pie -m elf_x86_64 --no-dynamic-linker --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -pie -m elf_x86_64 --no-dynamic-linker --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/pr19636-2l.d b/ld/testsuite/ld-x86-64/pr19636-2l.d
>index 1b894b3e97c..8c23c0b7411 100644
>--- a/ld/testsuite/ld-x86-64/pr19636-2l.d
>+++ b/ld/testsuite/ld-x86-64/pr19636-2l.d
>@@ -1,6 +1,6 @@
> #source: pr19636-2.s
> #as: --64 -mrelax-relocations=no
>-#ld: -pie -m elf_x86_64 --no-dynamic-linker --hash-style=sysv -z dynamic-undefined-weak -z max-page-size=0x200000 -z noseparate-code
>+#ld: -pie -m elf_x86_64 --no-dynamic-linker --hash-style=sysv -z dynamic-undefined-weak -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
> #warning: -z dynamic-undefined-weak ignored
>
>diff --git a/ld/testsuite/ld-x86-64/pr20253-1d.d b/ld/testsuite/ld-x86-64/pr20253-1d.d
>index f9f03ba8403..057577bdc57 100644
>--- a/ld/testsuite/ld-x86-64/pr20253-1d.d
>+++ b/ld/testsuite/ld-x86-64/pr20253-1d.d
>@@ -1,6 +1,6 @@
> #source: pr20253-1.s
> #as: --64
>-#ld: -pie -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -pie -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/pr20253-1f.d b/ld/testsuite/ld-x86-64/pr20253-1f.d
>index 6666bcaf147..479db8202e8 100644
>--- a/ld/testsuite/ld-x86-64/pr20253-1f.d
>+++ b/ld/testsuite/ld-x86-64/pr20253-1f.d
>@@ -1,6 +1,6 @@
> #source: pr20253-1.s
> #as: --64
>-#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/pr20253-1j.d b/ld/testsuite/ld-x86-64/pr20253-1j.d
>index 88c9715ad75..20176a2d357 100644
>--- a/ld/testsuite/ld-x86-64/pr20253-1j.d
>+++ b/ld/testsuite/ld-x86-64/pr20253-1j.d
>@@ -1,6 +1,6 @@
> #source: pr20253-1.s
> #as: --x32
>-#ld: -pie -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -pie -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/pr20253-1l.d b/ld/testsuite/ld-x86-64/pr20253-1l.d
>index 7428a721b16..4b179077dec 100644
>--- a/ld/testsuite/ld-x86-64/pr20253-1l.d
>+++ b/ld/testsuite/ld-x86-64/pr20253-1l.d
>@@ -1,6 +1,6 @@
> #source: pr20253-1.s
> #as: --x32
>-#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
>+#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> #objdump: -dw
>
> .*: +file format .*
>diff --git a/ld/testsuite/ld-x86-64/report-reloc-1-x32.d b/ld/testsuite/ld-x86-64/report-reloc-1-x32.d
>index c66f956c473..63fe7b1bb8a 100644
>--- a/ld/testsuite/ld-x86-64/report-reloc-1-x32.d
>+++ b/ld/testsuite/ld-x86-64/report-reloc-1-x32.d
>@@ -1,6 +1,6 @@
> #source: report-reloc-1.s
> #as: --x32
>-#ld: -pie -melf32_x86_64 -z report-relative-reloc
>+#ld: -pie -melf32_x86_64 -z report-relative-reloc $NO_DT_RELR_LDFLAGS
> #warning_output: report-reloc-1.l
> #readelf: -r --wide
>
>diff --git a/ld/testsuite/ld-x86-64/report-reloc-1.d b/ld/testsuite/ld-x86-64/report-reloc-1.d
>index 1b5f91fdd3f..69f164c9434 100644
>--- a/ld/testsuite/ld-x86-64/report-reloc-1.d
>+++ b/ld/testsuite/ld-x86-64/report-reloc-1.d
>@@ -1,6 +1,6 @@
> #source: report-reloc-1.s
> #as: --64
>-#ld: -pie -melf_x86_64 -z report-relative-reloc
>+#ld: -pie -melf_x86_64 -z report-relative-reloc $NO_DT_RELR_LDFLAGS
> #warning_output: report-reloc-1.l
> #readelf: -r --wide
>
>diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
>index c100879397e..b4048128057 100644
>--- a/ld/testsuite/ld-x86-64/x86-64.exp
>+++ b/ld/testsuite/ld-x86-64/x86-64.exp
>@@ -45,28 +45,6 @@ set x86_64tests {
>     {"basic PLT generation"
>      "-melf_x86_64 tmpdir/libpltlib.so" "" "--64" {plt.s}
>      {{objdump -drj.plt plt.pd}} "plt"}
>-    {"TLS -fpic -shared transitions"
>-     "-shared -melf_x86_64 --no-ld-generated-unwind-info \
>-      -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv" ""
>-     "--64" {tlspic1.s tlspic2.s}
>-     {{readelf -WSsrl tlspic.rd} {objdump -drj.text\ -Mintel64 tlspic.dd}
>-      {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
>-      "libtlspic.so"}
>-    {"TLS -fpic -shared transitions with r15 as GOT base"
>-     "-shared -melf_x86_64 --no-ld-generated-unwind-info \
>-      -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv" ""
>-     "--64 -mrelax-relocations=yes"
>-     {tlspic3.s tlspic2.s}
>-     {{readelf -WSsrl tlspic2.rd} {objdump -drj.text\ -Mintel64 tlspic2.dd}
>-      {objdump -sj.got tlspic2.sd} {objdump -sj.tdata tlspic2.td}}
>-      "libtlspic2.so"}
>-    {"TLS descriptor -fpic -shared transitions"
>-     "-shared -melf_x86_64 --no-ld-generated-unwind-info \
>-      -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv" ""
>-     "--64" {tlsdesc.s tlspic2.s}
>-     {{readelf -WSsrld tlsdesc.rd} {objdump -drj.text tlsdesc.dd}
>-      {objdump "-s -j.got -j.got.plt" tlsdesc.sd} {objdump -sj.tdata tlsdesc.td}
>-      {objdump -drj.plt tlsdesc.pd}} "libtlsdesc.so"}
>     {"Helper shared library" "-shared -melf_x86_64" ""
>      "--64" {tlslib.s} {} "libtlslib.so"}
>     {"TLS -fpic and -fno-pic exec transitions"
>@@ -240,6 +218,49 @@ set x86_64tests {
>
> run_ld_link_tests $x86_64tests
>
>+run_ld_link_tests [list \
>+    [list \
>+	"TLS -fpic -shared transitions" \
>+	"-shared -melf_x86_64 --no-ld-generated-unwind-info \
>+	 -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv \
>+	 $NO_DT_RELR_LDFLAGS" \
>+	"" "--64" \
>+	{tlspic1.s tlspic2.s} \
>+	{{readelf -WSsrl tlspic.rd} \
>+	 {objdump {-drj.text -Mintel64} tlspic.dd} \
>+	 {objdump -sj.got tlspic.sd} \
>+	 {objdump -sj.tdata tlspic.td}} \
>+	"libtlspic.so" \
>+    ] \
>+    [list \
>+	"TLS -fpic -shared transitions with r15 as GOT base" \
>+	"-shared -melf_x86_64 --no-ld-generated-unwind-info \
>+	 -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv \
>+	 $NO_DT_RELR_LDFLAGS" \
>+	 "" "--64 -mrelax-relocations=yes" \
>+	{tlspic3.s tlspic2.s} \
>+	{{readelf -WSsrl tlspic2.rd} \
>+	 {objdump {-drj.text -Mintel64} tlspic2.dd} \
>+	 {objdump -sj.got tlspic2.sd} \
>+	 {objdump -sj.tdata tlspic2.td}} \
>+	"libtlspic2.so" \
>+    ] \
>+    [list \
>+	"TLS descriptor -fpic -shared transitions" \
>+	"-shared -melf_x86_64 --no-ld-generated-unwind-info \
>+	 -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv \
>+	 $NO_DT_RELR_LDFLAGS" \
>+	"" "--64" \
>+	{tlsdesc.s tlspic2.s} \
>+	{{readelf -WSsrld tlsdesc.rd} \
>+	 {objdump -drj.text tlsdesc.dd} \
>+	 {objdump {-s -j.got -j.got.plt} tlsdesc.sd} \
>+	 {objdump -sj.tdata tlsdesc.td} \
>+	 {objdump -drj.plt tlsdesc.pd}} \
>+	 "libtlsdesc.so" \
>+    ] \
>+]
>+
> set test_name "Mixed x86_64 and i386 input test 1"
> set test mixed1
> if { ![ld_link $ld tmpdir/$test "-m$emul tmpdir/${test}a.o tmpdir/${test}b.o"] } {
>-- 
>2.33.1
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 09/10] ld: Add simple DT_RELR tests
  2022-01-08  2:39   ` Fangrui Song
@ 2022-01-08  2:44     ` H.J. Lu
  0 siblings, 0 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-08  2:44 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils, GNU C Library

On Fri, Jan 7, 2022 at 6:39 PM Fangrui Song <i@maskray.me> wrote:
>
> On 2022-01-07, H.J. Lu via Binutils wrote:
> >       * testsuite/ld-elf/dt-relr-1.s: New file.
> >       * testsuite/ld-elf/dt-relr-1a.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-1b.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-1c.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2.s: Likewise.
> >       * testsuite/ld-elf/dt-relr-2a.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2b.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2c.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2d.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2e.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2f.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2g.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2h.d: Likewise.
> >---
> > ld/testsuite/ld-elf/dt-relr-1.s  | 13 +++++++++++++
> > ld/testsuite/ld-elf/dt-relr-1a.d | 10 ++++++++++
> > ld/testsuite/ld-elf/dt-relr-1b.d |  9 +++++++++
> > ld/testsuite/ld-elf/dt-relr-1c.d |  9 +++++++++
> > ld/testsuite/ld-elf/dt-relr-2.s  | 20 ++++++++++++++++++++
> > ld/testsuite/ld-elf/dt-relr-2a.d | 10 ++++++++++
> > ld/testsuite/ld-elf/dt-relr-2b.d | 17 +++++++++++++++++
> > ld/testsuite/ld-elf/dt-relr-2c.d | 17 +++++++++++++++++
> > ld/testsuite/ld-elf/dt-relr-2d.d |  9 +++++++++
> > ld/testsuite/ld-elf/dt-relr-2e.d |  9 +++++++++
> > ld/testsuite/ld-elf/dt-relr-2f.d |  8 ++++++++
> > ld/testsuite/ld-elf/dt-relr-2g.d |  9 +++++++++
> > ld/testsuite/ld-elf/dt-relr-2h.d |  9 +++++++++
> > 13 files changed, 149 insertions(+)
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-1.s
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-1a.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-1b.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-1c.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2.s
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2a.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2b.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2c.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2d.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2e.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2f.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2g.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2h.d
> >
> >diff --git a/ld/testsuite/ld-elf/dt-relr-1.s b/ld/testsuite/ld-elf/dt-relr-1.s
> >new file mode 100644
> >index 00000000000..18486d3acb2
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-1.s
> >@@ -0,0 +1,13 @@
> >+      .text
> >+      .p2align 3
> >+      .globl _start
> >+_start:
> >+      .byte 0
> >+
> >+      .data
> >+      .p2align 3
> >+      .globl data
> >+data:
> >+      .byte 0
> >+      //  Offset is not a multiple of 2.  Don't use DT_RELR.
> >+      .dc.a __ehdr_start + 10
> >diff --git a/ld/testsuite/ld-elf/dt-relr-1a.d b/ld/testsuite/ld-elf/dt-relr-1a.d
> >new file mode 100644
> >index 00000000000..55c93cefb59
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-1a.d
> >@@ -0,0 +1,10 @@
> >+#source: dt-relr-1.s
> >+#ld: -e _start $DT_RELR_LDFLAGS
> >+#readelf: -rW -d
> >+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
> >+
> >+#...
> >+There is no dynamic section in this file.
> >+#...
> >+There are no relocations in this file.
> >+#pass
> >diff --git a/ld/testsuite/ld-elf/dt-relr-1b.d b/ld/testsuite/ld-elf/dt-relr-1b.d
> >new file mode 100644
> >index 00000000000..2b78f75d378
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-1b.d
> >@@ -0,0 +1,9 @@
> >+#source: dt-relr-1.s
> >+#ld: -e _start -pie $DT_RELR_LDFLAGS
> >+#readelf: -rW -d
> >+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
> >+
> >+#failif
> >+#...
> >+Relocation section '\.relr\.dyn' at offset .*
>
> Worth testing "contains XX entries" and "YY offsets".
>
> >+#pass
> >diff --git a/ld/testsuite/ld-elf/dt-relr-1c.d b/ld/testsuite/ld-elf/dt-relr-1c.d
> >new file mode 100644
> >index 00000000000..14f6cda6832
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-1c.d
> >@@ -0,0 +1,9 @@
> >+#source: dt-relr-1.s
> >+#ld: -shared $DT_RELR_LDFLAGS
> >+#readelf: -rW -d
> >+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
> >+
> >+#failif
> >+#...
> >+Relocation section '\.relr\.dyn' at offset .*
>
> Worth testing "contains XX entries" and "YY offsets".

These tests fail if there is a .relr.dyn section.  There is no
need to check more.

> >+#pass
> >diff --git a/ld/testsuite/ld-elf/dt-relr-2.s b/ld/testsuite/ld-elf/dt-relr-2.s
> >new file mode 100644
> >index 00000000000..c3917ee8c3a
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-2.s
> >@@ -0,0 +1,20 @@
> >+      .text
> >+      .p2align 3
> >+      .globl _start
> >+_start:
> >+      .byte 0
> >+
> >+      .data
> >+      .p2align 3
> >+      .globl data
> >+data:
> >+
> >+      .dc.a .data
> >+      .dc.a 0
> >+      .dc.a data + 2
> >+      .dc.a __ehdr_start + 4
> >+      .dc.a __ehdr_start + 9
> >+
> >+      .byte 0
> >+      //  Offset is not a multiple of 2.  Don't use DT_RELR.
> >+      .dc.a __ehdr_start + 10
> >diff --git a/ld/testsuite/ld-elf/dt-relr-2a.d b/ld/testsuite/ld-elf/dt-relr-2a.d
> >new file mode 100644
> >index 00000000000..31ef9e8e80e
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-2a.d
> >@@ -0,0 +1,10 @@
> >+#source: dt-relr-2.s
> >+#ld: -e _start $DT_RELR_LDFLAGS
> >+#readelf: -rW -d
> >+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
> >+
> >+#...
> >+There is no dynamic section in this file.
> >+#...
> >+There are no relocations in this file.
> >+#pass
> >diff --git a/ld/testsuite/ld-elf/dt-relr-2b.d b/ld/testsuite/ld-elf/dt-relr-2b.d
> >new file mode 100644
> >index 00000000000..7c401732a56
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-2b.d
> >@@ -0,0 +1,17 @@
> >+#source: dt-relr-2.s
> >+#ld: -e _start -pie $DT_RELR_LDFLAGS
> >+#readelf: -rW -d
> >+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
> >+
> >+#...
> >+ 0x[0-9a-f]+ \(RELR\)    +0x[0-9a-f]+
> >+ 0x[0-9a-f]+ \(RELRSZ\)  +(8|16) \(bytes\)
> >+ 0x[0-9a-f]+ \(RELRENT\) +(4|8) \(bytes\)
> >+#...
> >+Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 1 entry:
> >+#...
> >+[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .*
> >+#...
> >+Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
> >+  4 offsets
> >+#pass
> >diff --git a/ld/testsuite/ld-elf/dt-relr-2c.d b/ld/testsuite/ld-elf/dt-relr-2c.d
> >new file mode 100644
> >index 00000000000..63877b2f90f
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-2c.d
> >@@ -0,0 +1,17 @@
> >+#source: dt-relr-2.s
> >+#ld: -shared $DT_RELR_LDFLAGS
> >+#readelf: -rW -d
> >+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
> >+
> >+#...
> >+ 0x[0-9a-f]+ \(RELR\)    +0x[0-9a-f]+
> >+ 0x[0-9a-f]+ \(RELRSZ\)  +(8|16) \(bytes\)
> >+ 0x[0-9a-f]+ \(RELRENT\) +(4|8) \(bytes\)
> >+#...
> >+Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
> >+#...
> >+[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .*
> >+#...
> >+Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
> >+  3 offsets
> >+#pass
> >diff --git a/ld/testsuite/ld-elf/dt-relr-2d.d b/ld/testsuite/ld-elf/dt-relr-2d.d
> >new file mode 100644
> >index 00000000000..270a901f1a6
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-2d.d
> >@@ -0,0 +1,9 @@
> >+#source: dt-relr-2.s
> >+#ld: -e _start -pie $DT_RELR_LDFLAGS --no-relax
> >+#readelf: -rW -d
> >+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
> >+
> >+#failif
> >+#...
> >+Relocation section '\.relr\.dyn' at offset .*
> >+#pass
> >diff --git a/ld/testsuite/ld-elf/dt-relr-2e.d b/ld/testsuite/ld-elf/dt-relr-2e.d
> >new file mode 100644
> >index 00000000000..79ea62b096a
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-2e.d
> >@@ -0,0 +1,9 @@
> >+#source: dt-relr-2.s
> >+#ld: -e _start -pie $DT_RELR_LDFLAGS -z nocombreloc
> >+#readelf: -rW -d
> >+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
> >+
> >+#failif
> >+#...
> >+Relocation section '\.relr\.dyn' at offset .*
> >+#pass
> >diff --git a/ld/testsuite/ld-elf/dt-relr-2f.d b/ld/testsuite/ld-elf/dt-relr-2f.d
> >new file mode 100644
> >index 00000000000..4ad592f71fb
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-2f.d
> >@@ -0,0 +1,8 @@
> >+#source: dt-relr-2.s
> >+#ld: -r $DT_RELR_LDFLAGS
> >+#readelf: -rW
> >+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
> >+
> >+#...
> >+Relocation section '\.rel(a|)\.data' at offset 0x[0-9a-f]+ contains 5 entries:
> >+#pass
> >diff --git a/ld/testsuite/ld-elf/dt-relr-2g.d b/ld/testsuite/ld-elf/dt-relr-2g.d
> >new file mode 100644
> >index 00000000000..78e370068af
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-2g.d
> >@@ -0,0 +1,9 @@
> >+#source: dt-relr-2.s
> >+#ld: -e _start -pie $NO_DT_RELR_LDFLAGS
> >+#readelf: -rW -d
> >+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
> >+
> >+#failif
> >+#...
> >+Relocation section '\.relr\.dyn' at offset .*
> >+#pass
> >diff --git a/ld/testsuite/ld-elf/dt-relr-2h.d b/ld/testsuite/ld-elf/dt-relr-2h.d
> >new file mode 100644
> >index 00000000000..312373fb179
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-2h.d
> >@@ -0,0 +1,9 @@
> >+#source: dt-relr-2.s
> >+#ld: -e _start -shared $NO_DT_RELR_LDFLAGS
> >+#readelf: -rW -d
> >+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
> >+
> >+#failif
> >+#...
> >+Relocation section '\.relr\.dyn' at offset .*
> >+#pass
> >--
> >2.33.1
> >



-- 
H.J.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 10/10] ld: Add glibc dependency for DT_RELR
  2022-01-07 19:06 ` [PATCH 10/10] ld: Add glibc dependency for DT_RELR H.J. Lu
@ 2022-01-08  4:43   ` Fangrui Song
  2022-01-08  4:51     ` H.J. Lu
  0 siblings, 1 reply; 31+ messages in thread
From: Fangrui Song @ 2022-01-08  4:43 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, libc-alpha

On 2022-01-07, H.J. Lu via Binutils wrote:
>When DT_RELR is enabled, to avoid random run-time crash with older glibc
>binaries without DT_RELR support, add a GLIBC_ABI_DT_RELR symbol version,
>which is provided by glibc with DT_RELR support, dependency on the shared
>C library if it provides a GLIBC_2.XX symbol version.
>
>bfd/
>
>	* elflink.c (elf_link_add_dt_relr_dependency): New function.
>	(bfd_elf_size_dynamic_sections): Call
>	elf_link_add_dt_relr_dependency if DT_RELR is enabled.
>
>ld/
>
>	* ld.texi: Mention GLIBC_ABI_DT_RELR in -z pack-relative-relocs
>	entry.
>	* testsuite/ld-elf/dt-relr-glibc-1.c: New file.
>	* testsuite/ld-elf/dt-relr-glibc-1a.rd: Likewise.
>	* testsuite/ld-elf/dt-relr-glibc-1b.rd: Likewise.
>	* testsuite/ld-elf/dt-relr.exp: Likewise.
>---
> bfd/elflink.c                           | 86 +++++++++++++++++++++++++
> ld/ld.texi                              |  4 +-
> ld/testsuite/ld-elf/dt-relr-glibc-1.c   | 11 ++++
> ld/testsuite/ld-elf/dt-relr-glibc-1a.rd |  4 ++
> ld/testsuite/ld-elf/dt-relr-glibc-1b.rd |  7 ++
> ld/testsuite/ld-elf/dt-relr.exp         | 44 +++++++++++++
> 6 files changed, 155 insertions(+), 1 deletion(-)
> create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1.c
> create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1a.rd
> create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1b.rd
> create mode 100644 ld/testsuite/ld-elf/dt-relr.exp
>
>diff --git a/bfd/elflink.c b/bfd/elflink.c
>index 31b13f5df7a..05ac1cb7a63 100644
>--- a/bfd/elflink.c
>+++ b/bfd/elflink.c
>@@ -2213,6 +2213,85 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
>   return true;
> }
> \f
>+/* Return true if GLIBC_ABI_DT_RELR is added to the list of version
>+   dependencies successfully.  GLIBC_ABI_DT_RELR will be put into the
>+   .gnu.version_r section.  */
>+
>+static bool
>+elf_link_add_dt_relr_dependency (struct elf_find_verdep_info *rinfo)
>+{
>+  bfd *glibc_bfd = NULL;
>+  Elf_Internal_Verneed *t;
>+  Elf_Internal_Vernaux *a;
>+  size_t amt;
>+  const char *relr = "GLIBC_ABI_DT_RELR";
>+
>+  /* See if we already know about GLIBC_PRIVATE_DT_RELR.  */
>+  for (t = elf_tdata (rinfo->info->output_bfd)->verref;
>+       t != NULL;
>+       t = t->vn_nextref)
>+    {
>+      const char *soname = bfd_elf_get_dt_soname (t->vn_bfd);
>+      /* Skip the shared library if it isn't libc.so.  */
>+      if (!soname || !startswith (soname, "libc.so."))
>+	continue;

Having the dependency on ld.so is better.
(The linker knows the --dynamic-linker value.)
libc.so does not need to know whether DT_RELR is used.

It's also easier on glibc side.
Defining  __glibc_abi_dt_relr@@GLIBC_ABI_DT_RELR in elf/Versions is
simpler than defining it in libc.so and updating every libc.abilist.

>+      for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
>+	{
>+	  /* Return if GLIBC_PRIVATE_DT_RELR dependency has been
>+	     added.  */
>+	  if (a->vna_nodename == relr
>+	      || strcmp (a->vna_nodename, relr) == 0)
>+	    return true;
>+
>+	  /* Check if libc.so provides GLIBC_2.XX version.  */
>+	  if (!glibc_bfd && startswith (a->vna_nodename, "GLIBC_2."))
>+	    glibc_bfd = t->vn_bfd;
>+	}
>+
>+      break;
>+    }
>+
>+  /* Skip if it isn't linked against glibc.  */
>+  if (glibc_bfd == NULL)
>+    return true;
>+
>+  /* This is a new version.  Add it to tree we are building.  */
>+  if (t == NULL)
>+    {
>+      amt = sizeof *t;
>+      t = (Elf_Internal_Verneed *) bfd_zalloc (rinfo->info->output_bfd,
>+					       amt);
>+      if (t == NULL)
>+	{
>+	  rinfo->failed = true;
>+	  return false;
>+	}
>+
>+      t->vn_bfd = glibc_bfd;
>+      t->vn_nextref = elf_tdata (rinfo->info->output_bfd)->verref;
>+      elf_tdata (rinfo->info->output_bfd)->verref = t;
>+    }
>+
>+  amt = sizeof *a;
>+  a = (Elf_Internal_Vernaux *) bfd_zalloc (rinfo->info->output_bfd, amt);
>+  if (a == NULL)
>+    {
>+      rinfo->failed = true;
>+      return false;
>+    }
>+
>+  a->vna_nodename = relr;
>+  a->vna_flags = 0;
>+  a->vna_nextptr = t->vn_auxptr;
>+  a->vna_other = rinfo->vers + 1;
>+  ++rinfo->vers;
>+
>+  t->vn_auxptr = a;
>+
>+  return true;
>+}
>+
> /* Look through the symbols which are defined in other shared
>    libraries and referenced here.  Update the list of version
>    dependencies.  This will be put into the .gnu.version_r section.
>@@ -6940,6 +7019,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
>       if (sinfo.failed)
> 	return false;
>
>+      if (info->enable_dt_relr)
>+	{
>+	  elf_link_add_dt_relr_dependency (&sinfo);
>+	  if (sinfo.failed)
>+	    return false;
>+	}
>+
>       if (elf_tdata (output_bfd)->verref == NULL)
> 	s->flags |= SEC_EXCLUDE;
>       else
>diff --git a/ld/ld.texi b/ld/ld.texi
>index 457089ec06a..a16657ddb45 100644
>--- a/ld/ld.texi
>+++ b/ld/ld.texi
>@@ -1439,7 +1439,9 @@ and shared library.  It adds @code{DT_RELR}, @code{DT_RELRSZ} and
> building position-dependent executable and relocatable output.  This
> option also implies @option{combreloc} and @option{--relax}.
> @option{nopack-relative-relocs} is the default, which disables
>-compact relative relocation.  Supported for i386 and x86-64.
>+compact relative relocation.  When linked against the GNU C Library,
>+a GLIBC_ABI_DT_RELR symbol version dependency on the shared C Library
>+is added to the output.  Supported for i386 and x86-64.

> @item relro
> @itemx norelro
>diff --git a/ld/testsuite/ld-elf/dt-relr-glibc-1.c b/ld/testsuite/ld-elf/dt-relr-glibc-1.c
>new file mode 100644
>index 00000000000..beacffe29e7
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-glibc-1.c
>@@ -0,0 +1,11 @@
>+#define REL(n) \
>+  static int data##n; \
>+  void *p##n = &data##n;
>+
>+REL(1)
>+REL(2)
>+REL(3)
>+REL(4)
>+REL(5)
>+REL(6)
>+REL(7)
>diff --git a/ld/testsuite/ld-elf/dt-relr-glibc-1a.rd b/ld/testsuite/ld-elf/dt-relr-glibc-1a.rd
>new file mode 100644
>index 00000000000..51bda5d70a1
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-glibc-1a.rd
>@@ -0,0 +1,4 @@
>+#failif
>+#...
>+  0x[a-f0-9]+:   Name: GLIBC_ABI_DT_RELR  Flags: none  Version: [0-9]+
>+#...
>diff --git a/ld/testsuite/ld-elf/dt-relr-glibc-1b.rd b/ld/testsuite/ld-elf/dt-relr-glibc-1b.rd
>new file mode 100644
>index 00000000000..6556a6d939e
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-glibc-1b.rd
>@@ -0,0 +1,7 @@
>+#...
>+Version needs section '.gnu.version_r' contains 1 entry:
>+ Addr: 0x[0-9a-f]+ +Offset: 0x[0-9a-f]+ +Link: +[0-9]+ +\(.dynstr\)
>+ +0+: Version: 1 +File: libc\.so\.6(|\.1) +Cnt: +[0-9]+
>+#...
>+  0x[a-f0-9]+:   Name: GLIBC_ABI_DT_RELR  Flags: none  Version: [0-9]+
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr.exp b/ld/testsuite/ld-elf/dt-relr.exp
>new file mode 100644
>index 00000000000..51d21e400ab
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr.exp
>@@ -0,0 +1,44 @@
>+# Expect script for DT_RELR.
>+#   Copyright (C) 2022 Free Software Foundation, Inc.
>+#
>+# This file is part of the GNU Binutils.
>+#
>+# This program is free software; you can redistribute it and/or modify
>+# it under the terms of the GNU General Public License as published by
>+# the Free Software Foundation; either version 3 of the License, or
>+# (at your option) any later version.
>+#
>+# This program is distributed in the hope that it will be useful,
>+# but WITHOUT ANY WARRANTY; without even the implied warranty of
>+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>+# GNU General Public License for more details.
>+#
>+# You should have received a copy of the GNU General Public License
>+# along with this program; if not, write to the Free Software
>+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
>+# MA 02110-1301, USA.
>+#
>+
>+# Linux tests.
>+if { ![istarget "*-*-linux*"] } {
>+    return
>+}
>+
>+run_cc_link_tests [list \
>+    [list \
>+	"Build dt-relr-glibc-1a.so" \
>+	"-shared $NO_DT_RELR_CC_LDFLAGS" \
>+	"-fPIC" \
>+	{ dt-relr-glibc-1.c } \
>+	{{readelf {--version-info} dt-relr-glibc-1a.rd}} \
>+	"glibc-relr-1a.so" \
>+    ] \
>+    [list \
>+	"Build dt-relr-glibc-1b.so" \
>+	"-shared $DT_RELR_CC_LDFLAGS" \
>+	"-fPIC" \
>+	{ dt-relr-glibc-1.c } \
>+	{{readelf {-W --version-info} dt-relr-glibc-1b.rd}} \
>+	"dt-relr-glibc-1b.so" \
>+    ] \
>+]
>-- 
>2.33.1
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 10/10] ld: Add glibc dependency for DT_RELR
  2022-01-08  4:43   ` Fangrui Song
@ 2022-01-08  4:51     ` H.J. Lu
  2022-01-08  8:19       ` Fangrui Song
  0 siblings, 1 reply; 31+ messages in thread
From: H.J. Lu @ 2022-01-08  4:51 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils, GNU C Library

On Fri, Jan 7, 2022 at 8:43 PM Fangrui Song <i@maskray.me> wrote:
>
> On 2022-01-07, H.J. Lu via Binutils wrote:
> >When DT_RELR is enabled, to avoid random run-time crash with older glibc
> >binaries without DT_RELR support, add a GLIBC_ABI_DT_RELR symbol version,
> >which is provided by glibc with DT_RELR support, dependency on the shared
> >C library if it provides a GLIBC_2.XX symbol version.
> >
> >bfd/
> >
> >       * elflink.c (elf_link_add_dt_relr_dependency): New function.
> >       (bfd_elf_size_dynamic_sections): Call
> >       elf_link_add_dt_relr_dependency if DT_RELR is enabled.
> >
> >ld/
> >
> >       * ld.texi: Mention GLIBC_ABI_DT_RELR in -z pack-relative-relocs
> >       entry.
> >       * testsuite/ld-elf/dt-relr-glibc-1.c: New file.
> >       * testsuite/ld-elf/dt-relr-glibc-1a.rd: Likewise.
> >       * testsuite/ld-elf/dt-relr-glibc-1b.rd: Likewise.
> >       * testsuite/ld-elf/dt-relr.exp: Likewise.
> >---
> > bfd/elflink.c                           | 86 +++++++++++++++++++++++++
> > ld/ld.texi                              |  4 +-
> > ld/testsuite/ld-elf/dt-relr-glibc-1.c   | 11 ++++
> > ld/testsuite/ld-elf/dt-relr-glibc-1a.rd |  4 ++
> > ld/testsuite/ld-elf/dt-relr-glibc-1b.rd |  7 ++
> > ld/testsuite/ld-elf/dt-relr.exp         | 44 +++++++++++++
> > 6 files changed, 155 insertions(+), 1 deletion(-)
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1.c
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1a.rd
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1b.rd
> > create mode 100644 ld/testsuite/ld-elf/dt-relr.exp
> >
> >diff --git a/bfd/elflink.c b/bfd/elflink.c
> >index 31b13f5df7a..05ac1cb7a63 100644
> >--- a/bfd/elflink.c
> >+++ b/bfd/elflink.c
> >@@ -2213,6 +2213,85 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
> >   return true;
> > }
> >
> >+/* Return true if GLIBC_ABI_DT_RELR is added to the list of version
> >+   dependencies successfully.  GLIBC_ABI_DT_RELR will be put into the
> >+   .gnu.version_r section.  */
> >+
> >+static bool
> >+elf_link_add_dt_relr_dependency (struct elf_find_verdep_info *rinfo)
> >+{
> >+  bfd *glibc_bfd = NULL;
> >+  Elf_Internal_Verneed *t;
> >+  Elf_Internal_Vernaux *a;
> >+  size_t amt;
> >+  const char *relr = "GLIBC_ABI_DT_RELR";
> >+
> >+  /* See if we already know about GLIBC_PRIVATE_DT_RELR.  */
> >+  for (t = elf_tdata (rinfo->info->output_bfd)->verref;
> >+       t != NULL;
> >+       t = t->vn_nextref)
> >+    {
> >+      const char *soname = bfd_elf_get_dt_soname (t->vn_bfd);
> >+      /* Skip the shared library if it isn't libc.so.  */
> >+      if (!soname || !startswith (soname, "libc.so."))
> >+      continue;
>
> Having the dependency on ld.so is better.
> (The linker knows the --dynamic-linker value.)
> libc.so does not need to know whether DT_RELR is used.
>
> It's also easier on glibc side.
> Defining  __glibc_abi_dt_relr@@GLIBC_ABI_DT_RELR in elf/Versions is
> simpler than defining it in libc.so and updating every libc.abilist.

I chose libc.so instead of ld.so since shared libraries may
not be linked against ld.so.  The glibc change can be simple:

https://patchwork.sourceware.org/project/glibc/patch/20211123223053.3334224-1-hjl.tools@gmail.com/

Please replace GLIBC_ABI_VERSION_GEN2 with
GLIBC_ABI_DT_RELR.

or like

https://gitlab.com/x86-glibc/glibc/-/commit/3bc53baa5304855b5105dabd7726b23d454605fb

I can go either way.




> >+      for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
> >+      {
> >+        /* Return if GLIBC_PRIVATE_DT_RELR dependency has been
> >+           added.  */
> >+        if (a->vna_nodename == relr
> >+            || strcmp (a->vna_nodename, relr) == 0)
> >+          return true;
> >+
> >+        /* Check if libc.so provides GLIBC_2.XX version.  */
> >+        if (!glibc_bfd && startswith (a->vna_nodename, "GLIBC_2."))
> >+          glibc_bfd = t->vn_bfd;
> >+      }
> >+
> >+      break;
> >+    }
> >+
> >+  /* Skip if it isn't linked against glibc.  */
> >+  if (glibc_bfd == NULL)
> >+    return true;
> >+
> >+  /* This is a new version.  Add it to tree we are building.  */
> >+  if (t == NULL)
> >+    {
> >+      amt = sizeof *t;
> >+      t = (Elf_Internal_Verneed *) bfd_zalloc (rinfo->info->output_bfd,
> >+                                             amt);
> >+      if (t == NULL)
> >+      {
> >+        rinfo->failed = true;
> >+        return false;
> >+      }
> >+
> >+      t->vn_bfd = glibc_bfd;
> >+      t->vn_nextref = elf_tdata (rinfo->info->output_bfd)->verref;
> >+      elf_tdata (rinfo->info->output_bfd)->verref = t;
> >+    }
> >+
> >+  amt = sizeof *a;
> >+  a = (Elf_Internal_Vernaux *) bfd_zalloc (rinfo->info->output_bfd, amt);
> >+  if (a == NULL)
> >+    {
> >+      rinfo->failed = true;
> >+      return false;
> >+    }
> >+
> >+  a->vna_nodename = relr;
> >+  a->vna_flags = 0;
> >+  a->vna_nextptr = t->vn_auxptr;
> >+  a->vna_other = rinfo->vers + 1;
> >+  ++rinfo->vers;
> >+
> >+  t->vn_auxptr = a;
> >+
> >+  return true;
> >+}
> >+
> > /* Look through the symbols which are defined in other shared
> >    libraries and referenced here.  Update the list of version
> >    dependencies.  This will be put into the .gnu.version_r section.
> >@@ -6940,6 +7019,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
> >       if (sinfo.failed)
> >       return false;
> >
> >+      if (info->enable_dt_relr)
> >+      {
> >+        elf_link_add_dt_relr_dependency (&sinfo);
> >+        if (sinfo.failed)
> >+          return false;
> >+      }
> >+
> >       if (elf_tdata (output_bfd)->verref == NULL)
> >       s->flags |= SEC_EXCLUDE;
> >       else
> >diff --git a/ld/ld.texi b/ld/ld.texi
> >index 457089ec06a..a16657ddb45 100644
> >--- a/ld/ld.texi
> >+++ b/ld/ld.texi
> >@@ -1439,7 +1439,9 @@ and shared library.  It adds @code{DT_RELR}, @code{DT_RELRSZ} and
> > building position-dependent executable and relocatable output.  This
> > option also implies @option{combreloc} and @option{--relax}.
> > @option{nopack-relative-relocs} is the default, which disables
> >-compact relative relocation.  Supported for i386 and x86-64.
> >+compact relative relocation.  When linked against the GNU C Library,
> >+a GLIBC_ABI_DT_RELR symbol version dependency on the shared C Library
> >+is added to the output.  Supported for i386 and x86-64.
>
> > @item relro
> > @itemx norelro
> >diff --git a/ld/testsuite/ld-elf/dt-relr-glibc-1.c b/ld/testsuite/ld-elf/dt-relr-glibc-1.c
> >new file mode 100644
> >index 00000000000..beacffe29e7
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-glibc-1.c
> >@@ -0,0 +1,11 @@
> >+#define REL(n) \
> >+  static int data##n; \
> >+  void *p##n = &data##n;
> >+
> >+REL(1)
> >+REL(2)
> >+REL(3)
> >+REL(4)
> >+REL(5)
> >+REL(6)
> >+REL(7)
> >diff --git a/ld/testsuite/ld-elf/dt-relr-glibc-1a.rd b/ld/testsuite/ld-elf/dt-relr-glibc-1a.rd
> >new file mode 100644
> >index 00000000000..51bda5d70a1
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-glibc-1a.rd
> >@@ -0,0 +1,4 @@
> >+#failif
> >+#...
> >+  0x[a-f0-9]+:   Name: GLIBC_ABI_DT_RELR  Flags: none  Version: [0-9]+
> >+#...
> >diff --git a/ld/testsuite/ld-elf/dt-relr-glibc-1b.rd b/ld/testsuite/ld-elf/dt-relr-glibc-1b.rd
> >new file mode 100644
> >index 00000000000..6556a6d939e
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-glibc-1b.rd
> >@@ -0,0 +1,7 @@
> >+#...
> >+Version needs section '.gnu.version_r' contains 1 entry:
> >+ Addr: 0x[0-9a-f]+ +Offset: 0x[0-9a-f]+ +Link: +[0-9]+ +\(.dynstr\)
> >+ +0+: Version: 1 +File: libc\.so\.6(|\.1) +Cnt: +[0-9]+
> >+#...
> >+  0x[a-f0-9]+:   Name: GLIBC_ABI_DT_RELR  Flags: none  Version: [0-9]+
> >+#pass
> >diff --git a/ld/testsuite/ld-elf/dt-relr.exp b/ld/testsuite/ld-elf/dt-relr.exp
> >new file mode 100644
> >index 00000000000..51d21e400ab
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr.exp
> >@@ -0,0 +1,44 @@
> >+# Expect script for DT_RELR.
> >+#   Copyright (C) 2022 Free Software Foundation, Inc.
> >+#
> >+# This file is part of the GNU Binutils.
> >+#
> >+# This program is free software; you can redistribute it and/or modify
> >+# it under the terms of the GNU General Public License as published by
> >+# the Free Software Foundation; either version 3 of the License, or
> >+# (at your option) any later version.
> >+#
> >+# This program is distributed in the hope that it will be useful,
> >+# but WITHOUT ANY WARRANTY; without even the implied warranty of
> >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >+# GNU General Public License for more details.
> >+#
> >+# You should have received a copy of the GNU General Public License
> >+# along with this program; if not, write to the Free Software
> >+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
> >+# MA 02110-1301, USA.
> >+#
> >+
> >+# Linux tests.
> >+if { ![istarget "*-*-linux*"] } {
> >+    return
> >+}
> >+
> >+run_cc_link_tests [list \
> >+    [list \
> >+      "Build dt-relr-glibc-1a.so" \
> >+      "-shared $NO_DT_RELR_CC_LDFLAGS" \
> >+      "-fPIC" \
> >+      { dt-relr-glibc-1.c } \
> >+      {{readelf {--version-info} dt-relr-glibc-1a.rd}} \
> >+      "glibc-relr-1a.so" \
> >+    ] \
> >+    [list \
> >+      "Build dt-relr-glibc-1b.so" \
> >+      "-shared $DT_RELR_CC_LDFLAGS" \
> >+      "-fPIC" \
> >+      { dt-relr-glibc-1.c } \
> >+      {{readelf {-W --version-info} dt-relr-glibc-1b.rd}} \
> >+      "dt-relr-glibc-1b.so" \
> >+    ] \
> >+]
> >--
> >2.33.1
> >



--
H.J.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 10/10] ld: Add glibc dependency for DT_RELR
  2022-01-08  4:51     ` H.J. Lu
@ 2022-01-08  8:19       ` Fangrui Song
  2022-01-08 18:37         ` H.J. Lu
  0 siblings, 1 reply; 31+ messages in thread
From: Fangrui Song @ 2022-01-08  8:19 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils, GNU C Library

On 2022-01-07, H.J. Lu wrote:
>On Fri, Jan 7, 2022 at 8:43 PM Fangrui Song <i@maskray.me> wrote:
>>
>> On 2022-01-07, H.J. Lu via Binutils wrote:
>> >When DT_RELR is enabled, to avoid random run-time crash with older glibc
>> >binaries without DT_RELR support, add a GLIBC_ABI_DT_RELR symbol version,
>> >which is provided by glibc with DT_RELR support, dependency on the shared
>> >C library if it provides a GLIBC_2.XX symbol version.
>> >
>> >bfd/
>> >
>> >       * elflink.c (elf_link_add_dt_relr_dependency): New function.
>> >       (bfd_elf_size_dynamic_sections): Call
>> >       elf_link_add_dt_relr_dependency if DT_RELR is enabled.
>> >
>> >ld/
>> >
>> >       * ld.texi: Mention GLIBC_ABI_DT_RELR in -z pack-relative-relocs
>> >       entry.
>> >       * testsuite/ld-elf/dt-relr-glibc-1.c: New file.
>> >       * testsuite/ld-elf/dt-relr-glibc-1a.rd: Likewise.
>> >       * testsuite/ld-elf/dt-relr-glibc-1b.rd: Likewise.
>> >       * testsuite/ld-elf/dt-relr.exp: Likewise.
>> >---
>> > bfd/elflink.c                           | 86 +++++++++++++++++++++++++
>> > ld/ld.texi                              |  4 +-
>> > ld/testsuite/ld-elf/dt-relr-glibc-1.c   | 11 ++++
>> > ld/testsuite/ld-elf/dt-relr-glibc-1a.rd |  4 ++
>> > ld/testsuite/ld-elf/dt-relr-glibc-1b.rd |  7 ++
>> > ld/testsuite/ld-elf/dt-relr.exp         | 44 +++++++++++++
>> > 6 files changed, 155 insertions(+), 1 deletion(-)
>> > create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1.c
>> > create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1a.rd
>> > create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1b.rd
>> > create mode 100644 ld/testsuite/ld-elf/dt-relr.exp
>> >
>> >diff --git a/bfd/elflink.c b/bfd/elflink.c
>> >index 31b13f5df7a..05ac1cb7a63 100644
>> >--- a/bfd/elflink.c
>> >+++ b/bfd/elflink.c
>> >@@ -2213,6 +2213,85 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
>> >   return true;
>> > }
>> >
>> >+/* Return true if GLIBC_ABI_DT_RELR is added to the list of version
>> >+   dependencies successfully.  GLIBC_ABI_DT_RELR will be put into the
>> >+   .gnu.version_r section.  */
>> >+
>> >+static bool
>> >+elf_link_add_dt_relr_dependency (struct elf_find_verdep_info *rinfo)
>> >+{
>> >+  bfd *glibc_bfd = NULL;
>> >+  Elf_Internal_Verneed *t;
>> >+  Elf_Internal_Vernaux *a;
>> >+  size_t amt;
>> >+  const char *relr = "GLIBC_ABI_DT_RELR";
>> >+
>> >+  /* See if we already know about GLIBC_PRIVATE_DT_RELR.  */
>> >+  for (t = elf_tdata (rinfo->info->output_bfd)->verref;
>> >+       t != NULL;
>> >+       t = t->vn_nextref)
>> >+    {
>> >+      const char *soname = bfd_elf_get_dt_soname (t->vn_bfd);
>> >+      /* Skip the shared library if it isn't libc.so.  */
>> >+      if (!soname || !startswith (soname, "libc.so."))
>> >+      continue;
>>
>> Having the dependency on ld.so is better.
>> (The linker knows the --dynamic-linker value.)
>> libc.so does not need to know whether DT_RELR is used.
>>
>> It's also easier on glibc side.
>> Defining  __glibc_abi_dt_relr@@GLIBC_ABI_DT_RELR in elf/Versions is
>> simpler than defining it in libc.so and updating every libc.abilist.
>
>I chose libc.so instead of ld.so since shared libraries may
>not be linked against ld.so.  The glibc change can be simple:
>
>https://patchwork.sourceware.org/project/glibc/patch/20211123223053.3334224-1-hjl.tools@gmail.com/
>
>Please replace GLIBC_ABI_VERSION_GEN2 with
>GLIBC_ABI_DT_RELR.
>
>or like
>
>https://gitlab.com/x86-glibc/glibc/-/commit/3bc53baa5304855b5105dabd7726b23d454605fb
>
>I can go either way.

OK... I picked the first way:
https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/maskray/relr

>
>
>
>> >+      for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
>> >+      {
>> >+        /* Return if GLIBC_PRIVATE_DT_RELR dependency has been
>> >+           added.  */
>> >+        if (a->vna_nodename == relr
>> >+            || strcmp (a->vna_nodename, relr) == 0)
>> >+          return true;
>> >+
>> >+        /* Check if libc.so provides GLIBC_2.XX version.  */
>> >+        if (!glibc_bfd && startswith (a->vna_nodename, "GLIBC_2."))
>> >+          glibc_bfd = t->vn_bfd;
>> >+      }
>> >+
>> >+      break;
>> >+    }
>> >+
>> >+  /* Skip if it isn't linked against glibc.  */
>> >+  if (glibc_bfd == NULL)
>> >+    return true;
>> >+
>> >+  /* This is a new version.  Add it to tree we are building.  */
>> >+  if (t == NULL)
>> >+    {
>> >+      amt = sizeof *t;
>> >+      t = (Elf_Internal_Verneed *) bfd_zalloc (rinfo->info->output_bfd,
>> >+                                             amt);
>> >+      if (t == NULL)
>> >+      {
>> >+        rinfo->failed = true;
>> >+        return false;
>> >+      }
>> >+
>> >+      t->vn_bfd = glibc_bfd;
>> >+      t->vn_nextref = elf_tdata (rinfo->info->output_bfd)->verref;
>> >+      elf_tdata (rinfo->info->output_bfd)->verref = t;
>> >+    }
>> >+
>> >+  amt = sizeof *a;
>> >+  a = (Elf_Internal_Vernaux *) bfd_zalloc (rinfo->info->output_bfd, amt);
>> >+  if (a == NULL)
>> >+    {
>> >+      rinfo->failed = true;
>> >+      return false;
>> >+    }
>> >+
>> >+  a->vna_nodename = relr;
>> >+  a->vna_flags = 0;
>> >+  a->vna_nextptr = t->vn_auxptr;
>> >+  a->vna_other = rinfo->vers + 1;
>> >+  ++rinfo->vers;
>> >+
>> >+  t->vn_auxptr = a;
>> >+
>> >+  return true;
>> >+}
>> >+
>> > /* Look through the symbols which are defined in other shared
>> >    libraries and referenced here.  Update the list of version
>> >    dependencies.  This will be put into the .gnu.version_r section.
>> >@@ -6940,6 +7019,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
>> >       if (sinfo.failed)
>> >       return false;
>> >
>> >+      if (info->enable_dt_relr)
>> >+      {
>> >+        elf_link_add_dt_relr_dependency (&sinfo);
>> >+        if (sinfo.failed)
>> >+          return false;
>> >+      }
>> >+
>> >       if (elf_tdata (output_bfd)->verref == NULL)
>> >       s->flags |= SEC_EXCLUDE;
>> >       else
>> >diff --git a/ld/ld.texi b/ld/ld.texi
>> >index 457089ec06a..a16657ddb45 100644
>> >--- a/ld/ld.texi
>> >+++ b/ld/ld.texi
>> >@@ -1439,7 +1439,9 @@ and shared library.  It adds @code{DT_RELR}, @code{DT_RELRSZ} and
>> > building position-dependent executable and relocatable output.  This
>> > option also implies @option{combreloc} and @option{--relax}.
>> > @option{nopack-relative-relocs} is the default, which disables
>> >-compact relative relocation.  Supported for i386 and x86-64.
>> >+compact relative relocation.  When linked against the GNU C Library,
>> >+a GLIBC_ABI_DT_RELR symbol version dependency on the shared C Library
>> >+is added to the output.  Supported for i386 and x86-64.
>>
>> > @item relro
>> > @itemx norelro
>> >diff --git a/ld/testsuite/ld-elf/dt-relr-glibc-1.c b/ld/testsuite/ld-elf/dt-relr-glibc-1.c
>> >new file mode 100644
>> >index 00000000000..beacffe29e7
>> >--- /dev/null
>> >+++ b/ld/testsuite/ld-elf/dt-relr-glibc-1.c
>> >@@ -0,0 +1,11 @@
>> >+#define REL(n) \
>> >+  static int data##n; \
>> >+  void *p##n = &data##n;
>> >+
>> >+REL(1)
>> >+REL(2)
>> >+REL(3)
>> >+REL(4)
>> >+REL(5)
>> >+REL(6)
>> >+REL(7)
>> >diff --git a/ld/testsuite/ld-elf/dt-relr-glibc-1a.rd b/ld/testsuite/ld-elf/dt-relr-glibc-1a.rd
>> >new file mode 100644
>> >index 00000000000..51bda5d70a1
>> >--- /dev/null
>> >+++ b/ld/testsuite/ld-elf/dt-relr-glibc-1a.rd
>> >@@ -0,0 +1,4 @@
>> >+#failif
>> >+#...
>> >+  0x[a-f0-9]+:   Name: GLIBC_ABI_DT_RELR  Flags: none  Version: [0-9]+
>> >+#...
>> >diff --git a/ld/testsuite/ld-elf/dt-relr-glibc-1b.rd b/ld/testsuite/ld-elf/dt-relr-glibc-1b.rd
>> >new file mode 100644
>> >index 00000000000..6556a6d939e
>> >--- /dev/null
>> >+++ b/ld/testsuite/ld-elf/dt-relr-glibc-1b.rd
>> >@@ -0,0 +1,7 @@
>> >+#...
>> >+Version needs section '.gnu.version_r' contains 1 entry:
>> >+ Addr: 0x[0-9a-f]+ +Offset: 0x[0-9a-f]+ +Link: +[0-9]+ +\(.dynstr\)
>> >+ +0+: Version: 1 +File: libc\.so\.6(|\.1) +Cnt: +[0-9]+
>> >+#...
>> >+  0x[a-f0-9]+:   Name: GLIBC_ABI_DT_RELR  Flags: none  Version: [0-9]+
>> >+#pass
>> >diff --git a/ld/testsuite/ld-elf/dt-relr.exp b/ld/testsuite/ld-elf/dt-relr.exp
>> >new file mode 100644
>> >index 00000000000..51d21e400ab
>> >--- /dev/null
>> >+++ b/ld/testsuite/ld-elf/dt-relr.exp
>> >@@ -0,0 +1,44 @@
>> >+# Expect script for DT_RELR.
>> >+#   Copyright (C) 2022 Free Software Foundation, Inc.
>> >+#
>> >+# This file is part of the GNU Binutils.
>> >+#
>> >+# This program is free software; you can redistribute it and/or modify
>> >+# it under the terms of the GNU General Public License as published by
>> >+# the Free Software Foundation; either version 3 of the License, or
>> >+# (at your option) any later version.
>> >+#
>> >+# This program is distributed in the hope that it will be useful,
>> >+# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> >+# GNU General Public License for more details.
>> >+#
>> >+# You should have received a copy of the GNU General Public License
>> >+# along with this program; if not, write to the Free Software
>> >+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
>> >+# MA 02110-1301, USA.
>> >+#
>> >+
>> >+# Linux tests.
>> >+if { ![istarget "*-*-linux*"] } {
>> >+    return
>> >+}
>> >+
>> >+run_cc_link_tests [list \
>> >+    [list \
>> >+      "Build dt-relr-glibc-1a.so" \
>> >+      "-shared $NO_DT_RELR_CC_LDFLAGS" \
>> >+      "-fPIC" \
>> >+      { dt-relr-glibc-1.c } \
>> >+      {{readelf {--version-info} dt-relr-glibc-1a.rd}} \
>> >+      "glibc-relr-1a.so" \
>> >+    ] \
>> >+    [list \
>> >+      "Build dt-relr-glibc-1b.so" \
>> >+      "-shared $DT_RELR_CC_LDFLAGS" \
>> >+      "-fPIC" \
>> >+      { dt-relr-glibc-1.c } \
>> >+      {{readelf {-W --version-info} dt-relr-glibc-1b.rd}} \
>> >+      "dt-relr-glibc-1b.so" \
>> >+    ] \
>> >+]
>> >--
>> >2.33.1
>> >
>
>
>
>--
>H.J.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 05/10] ld: Initial DT_RELR support
  2022-01-07 19:06 ` [PATCH 05/10] ld: Initial DT_RELR support H.J. Lu
  2022-01-08  2:10   ` Fangrui Song
@ 2022-01-08  8:30   ` Fangrui Song
  2022-01-08 13:19     ` H.J. Lu
  1 sibling, 1 reply; 31+ messages in thread
From: Fangrui Song @ 2022-01-08  8:30 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, libc-alpha

On 2022-01-07, H.J. Lu via Binutils wrote:
>Add a -z pack-relative-relocs option to enable DT_RELR and create a
>relr.dyn section for DT_RELR.
>
>-z pack-relative-relocs implies -z combreloc and --relax.  --no-relax
>and -z nocombreloc imply -z nopack-relative-relocs.
>
>-z pack-relative-relocs is chosen over the similar option in lld,
>--pack-dyn-relocs=relr, to implement a glibc binary lockout mechanism
>with a special glibc version symbol, to avoid random crashes of DT_RELR
>binaries with the existing glibc binaries.

I think -z pack-relative-relocs is orthogonal to -z combreloc.
-z combreloc affects how .rela.dyn is sorted and whether RELACOUNT is
generated. It has nothing to do with .relr.dyn, which is a different section.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 09/10] ld: Add simple DT_RELR tests
  2022-01-07 19:06 ` [PATCH 09/10] ld: Add simple DT_RELR tests H.J. Lu
  2022-01-08  2:39   ` Fangrui Song
@ 2022-01-08  8:37   ` Fangrui Song
  2022-01-08 18:33     ` H.J. Lu
  1 sibling, 1 reply; 31+ messages in thread
From: Fangrui Song @ 2022-01-08  8:37 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, libc-alpha

On 2022-01-07, H.J. Lu via Binutils wrote:
>	* testsuite/ld-elf/dt-relr-1.s: New file.
>	* testsuite/ld-elf/dt-relr-1a.d: Likewise.
>	* testsuite/ld-elf/dt-relr-1b.d: Likewise.
>	* testsuite/ld-elf/dt-relr-1c.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2.s: Likewise.
>	* testsuite/ld-elf/dt-relr-2a.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2b.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2c.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2d.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2e.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2f.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2g.d: Likewise.
>	* testsuite/ld-elf/dt-relr-2h.d: Likewise.
>---
> ld/testsuite/ld-elf/dt-relr-1.s  | 13 +++++++++++++
> ld/testsuite/ld-elf/dt-relr-1a.d | 10 ++++++++++
> ld/testsuite/ld-elf/dt-relr-1b.d |  9 +++++++++
> ld/testsuite/ld-elf/dt-relr-1c.d |  9 +++++++++
> ld/testsuite/ld-elf/dt-relr-2.s  | 20 ++++++++++++++++++++
> ld/testsuite/ld-elf/dt-relr-2a.d | 10 ++++++++++
> ld/testsuite/ld-elf/dt-relr-2b.d | 17 +++++++++++++++++
> ld/testsuite/ld-elf/dt-relr-2c.d | 17 +++++++++++++++++
> ld/testsuite/ld-elf/dt-relr-2d.d |  9 +++++++++
> ld/testsuite/ld-elf/dt-relr-2e.d |  9 +++++++++
> ld/testsuite/ld-elf/dt-relr-2f.d |  8 ++++++++
> ld/testsuite/ld-elf/dt-relr-2g.d |  9 +++++++++
> ld/testsuite/ld-elf/dt-relr-2h.d |  9 +++++++++
> 13 files changed, 149 insertions(+)
> create mode 100644 ld/testsuite/ld-elf/dt-relr-1.s
> create mode 100644 ld/testsuite/ld-elf/dt-relr-1a.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-1b.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-1c.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2.s
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2a.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2b.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2c.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2d.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2e.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2f.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2g.d
> create mode 100644 ld/testsuite/ld-elf/dt-relr-2h.d
>
>diff --git a/ld/testsuite/ld-elf/dt-relr-1.s b/ld/testsuite/ld-elf/dt-relr-1.s
>new file mode 100644
>index 00000000000..18486d3acb2
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-1.s
>@@ -0,0 +1,13 @@
>+	.text
>+	.p2align 3
>+	.globl _start
>+_start:
>+	.byte 0
>+
>+	.data
>+	.p2align 3
>+	.globl data
>+data:
>+	.byte 0
>+	//  Offset is not a multiple of 2.  Don't use DT_RELR.
>+	.dc.a __ehdr_start + 10

.data
.balign 1
.dc.a .data

may be worth adding as a test.

Currently R_X86_64_RELATIVE is used even if its r_offset is even.
There is conservative but safe as it's difficult to ensure an input
section's address is even when its alignment is 1.

>diff --git a/ld/testsuite/ld-elf/dt-relr-1a.d b/ld/testsuite/ld-elf/dt-relr-1a.d
>new file mode 100644
>index 00000000000..55c93cefb59
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-1a.d
>@@ -0,0 +1,10 @@
>+#source: dt-relr-1.s
>+#ld: -e _start $DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#...
>+There is no dynamic section in this file.
>+#...
>+There are no relocations in this file.
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-1b.d b/ld/testsuite/ld-elf/dt-relr-1b.d
>new file mode 100644
>index 00000000000..2b78f75d378
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-1b.d
>@@ -0,0 +1,9 @@
>+#source: dt-relr-1.s
>+#ld: -e _start -pie $DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#failif
>+#...
>+Relocation section '\.relr\.dyn' at offset .*
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-1c.d b/ld/testsuite/ld-elf/dt-relr-1c.d
>new file mode 100644
>index 00000000000..14f6cda6832
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-1c.d
>@@ -0,0 +1,9 @@
>+#source: dt-relr-1.s
>+#ld: -shared $DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#failif
>+#...
>+Relocation section '\.relr\.dyn' at offset .*
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2.s b/ld/testsuite/ld-elf/dt-relr-2.s
>new file mode 100644
>index 00000000000..c3917ee8c3a
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2.s
>@@ -0,0 +1,20 @@
>+	.text
>+	.p2align 3
>+	.globl _start
>+_start:
>+	.byte 0
>+
>+	.data
>+	.p2align 3
>+	.globl data
>+data:
>+
>+	.dc.a .data
>+	.dc.a 0
>+	.dc.a data + 2
>+	.dc.a __ehdr_start + 4
>+	.dc.a __ehdr_start + 9
>+
>+	.byte 0
>+	//  Offset is not a multiple of 2.  Don't use DT_RELR.
>+	.dc.a __ehdr_start + 10
>diff --git a/ld/testsuite/ld-elf/dt-relr-2a.d b/ld/testsuite/ld-elf/dt-relr-2a.d
>new file mode 100644
>index 00000000000..31ef9e8e80e
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2a.d
>@@ -0,0 +1,10 @@
>+#source: dt-relr-2.s
>+#ld: -e _start $DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#...
>+There is no dynamic section in this file.
>+#...
>+There are no relocations in this file.
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2b.d b/ld/testsuite/ld-elf/dt-relr-2b.d
>new file mode 100644
>index 00000000000..7c401732a56
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2b.d
>@@ -0,0 +1,17 @@
>+#source: dt-relr-2.s
>+#ld: -e _start -pie $DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#...
>+ 0x[0-9a-f]+ \(RELR\)    +0x[0-9a-f]+
>+ 0x[0-9a-f]+ \(RELRSZ\)  +(8|16) \(bytes\)
>+ 0x[0-9a-f]+ \(RELRENT\) +(4|8) \(bytes\)
>+#...
>+Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 1 entry:
>+#...
>+[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .*
>+#...
>+Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
>+  4 offsets
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2c.d b/ld/testsuite/ld-elf/dt-relr-2c.d
>new file mode 100644
>index 00000000000..63877b2f90f
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2c.d
>@@ -0,0 +1,17 @@
>+#source: dt-relr-2.s
>+#ld: -shared $DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#...
>+ 0x[0-9a-f]+ \(RELR\)    +0x[0-9a-f]+
>+ 0x[0-9a-f]+ \(RELRSZ\)  +(8|16) \(bytes\)
>+ 0x[0-9a-f]+ \(RELRENT\) +(4|8) \(bytes\)
>+#...
>+Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
>+#...
>+[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .*
>+#...
>+Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
>+  3 offsets
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2d.d b/ld/testsuite/ld-elf/dt-relr-2d.d
>new file mode 100644
>index 00000000000..270a901f1a6
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2d.d
>@@ -0,0 +1,9 @@
>+#source: dt-relr-2.s
>+#ld: -e _start -pie $DT_RELR_LDFLAGS --no-relax
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#failif
>+#...
>+Relocation section '\.relr\.dyn' at offset .*
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2e.d b/ld/testsuite/ld-elf/dt-relr-2e.d
>new file mode 100644
>index 00000000000..79ea62b096a
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2e.d
>@@ -0,0 +1,9 @@
>+#source: dt-relr-2.s
>+#ld: -e _start -pie $DT_RELR_LDFLAGS -z nocombreloc
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#failif
>+#...
>+Relocation section '\.relr\.dyn' at offset .*
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2f.d b/ld/testsuite/ld-elf/dt-relr-2f.d
>new file mode 100644
>index 00000000000..4ad592f71fb
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2f.d
>@@ -0,0 +1,8 @@
>+#source: dt-relr-2.s
>+#ld: -r $DT_RELR_LDFLAGS
>+#readelf: -rW
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#...
>+Relocation section '\.rel(a|)\.data' at offset 0x[0-9a-f]+ contains 5 entries:
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2g.d b/ld/testsuite/ld-elf/dt-relr-2g.d
>new file mode 100644
>index 00000000000..78e370068af
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2g.d
>@@ -0,0 +1,9 @@
>+#source: dt-relr-2.s
>+#ld: -e _start -pie $NO_DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#failif
>+#...
>+Relocation section '\.relr\.dyn' at offset .*
>+#pass
>diff --git a/ld/testsuite/ld-elf/dt-relr-2h.d b/ld/testsuite/ld-elf/dt-relr-2h.d
>new file mode 100644
>index 00000000000..312373fb179
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dt-relr-2h.d
>@@ -0,0 +1,9 @@
>+#source: dt-relr-2.s
>+#ld: -e _start -shared $NO_DT_RELR_LDFLAGS
>+#readelf: -rW -d
>+#target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
>+
>+#failif
>+#...
>+Relocation section '\.relr\.dyn' at offset .*
>+#pass
>-- 
>2.33.1
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 05/10] ld: Initial DT_RELR support
  2022-01-08  8:30   ` Fangrui Song
@ 2022-01-08 13:19     ` H.J. Lu
  0 siblings, 0 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-08 13:19 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils, GNU C Library

On Sat, Jan 8, 2022 at 12:30 AM Fangrui Song <i@maskray.me> wrote:
>
> On 2022-01-07, H.J. Lu via Binutils wrote:
> >Add a -z pack-relative-relocs option to enable DT_RELR and create a
> >relr.dyn section for DT_RELR.
> >
> >-z pack-relative-relocs implies -z combreloc and --relax.  --no-relax
> >and -z nocombreloc imply -z nopack-relative-relocs.
> >
> >-z pack-relative-relocs is chosen over the similar option in lld,
> >--pack-dyn-relocs=relr, to implement a glibc binary lockout mechanism
> >with a special glibc version symbol, to avoid random crashes of DT_RELR
> >binaries with the existing glibc binaries.
>
> I think -z pack-relative-relocs is orthogonal to -z combreloc.
> -z combreloc affects how .rela.dyn is sorted and whether RELACOUNT is
> generated. It has nothing to do with .relr.dyn, which is a different section.

With -z nocombreloc, ld can generate:

$ readelf -r tmpdir/pr25754-3ba

Relocation section '.rela.data.rel.ro' at offset 0x540 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000003de8  000000000008 R_X86_64_RELATIVE                    3de8

Relocation section '.rela.got' at offset 0x558 contains 5 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000003fd0  000100000006 R_X86_64_GLOB_DAT 0000000000000000
__libc_start_main@GLIBC_2.34 + 0
000000003fd8  000200000006 R_X86_64_GLOB_DAT 0000000000000000
_ITM_deregisterTM[...] + 0
000000003fe8  000400000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000003ff0  000500000006 R_X86_64_GLOB_DAT 0000000000000000
_ITM_registerTMCl[...] + 0
000000003ff8  000600000006 R_X86_64_GLOB_DAT 0000000000000000
__cxa_finalize@GLIBC_2.2.5 + 0

Relocation section '.rela.fini_array' at offset 0x5d0 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000003de0  000000000008 R_X86_64_RELATIVE                    10f0

Relocation section '.rela.init_array' at offset 0x5e8 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000003dd8  000000000008 R_X86_64_RELATIVE                    1130

Relocation section '.rela.plt' at offset 0x600 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000004018  000300000007 R_X86_64_JUMP_SLO 0000000000000000
puts@GLIBC_2.2.5 + 0

3 R_X86_64_RELATIVEs are 3 different .rela sections.
If they are put in a single section, they are combined.

-- 
H.J.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 07/10] elf: Support DT_RELR in linker tests
  2022-01-08  2:42   ` Fangrui Song
@ 2022-01-08 13:46     ` H.J. Lu
  0 siblings, 0 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-08 13:46 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils, GNU C Library

On Fri, Jan 7, 2022 at 6:42 PM Fangrui Song <i@maskray.me> wrote:
>
>
> On 2022-01-07, H.J. Lu via Binutils wrote:
> >Allow eabling and disabling DT_RELR in linker tests.  Disable DT_RELR in
> >linker tests which don't expect DT_RELR in linker outputs.
> >
> >binutils/
> >
> >       * testsuite/lib/binutils-common.exp (run_dump_test): Make
> >       DT_RELR_LDFLAGS and NO_DT_RELR_LDFLAGS global.
> >
> >ld/
> >
> >       * testsuite/config/default.exp (DT_RELR_LDFLAGS): New.
> >       (DT_RELR_CC_LDFLAGS): Likewise.
> >       (NO_DT_RELR_LDFLAGS): Likewise.
> >       (NO_DT_RELR_CC_LDFLAGS): Likewise.
> >       * testsuite/ld-elf/shared.exp: Pass $NO_DT_RELR_LDFLAGS to
> >       linker for some tests.
> >       * testsuite/ld-i386/export-class.exp: Likewise.
> >       * testsuite/ld-i386/i386.exp: Likewise.
> >       * testsuite/ld-i386/ibt-plt-2a.d: Pass $NO_DT_RELR_LDFLAGS to
> >       linker.
> >       * testsuite/ld-i386/ibt-plt-3a.d: Likewise.
> >       * testsuite/ld-i386/ibt-plt-3c.d: Likewise.
> >       * testsuite/ld-i386/report-reloc-1.d: Likewise.
> >       * testsuite/ld-ifunc/ifunc-2-i386-now.d: Likewise.
> >       * testsuite/ld-ifunc/ifunc-2-local-i386-now.d: Likewise.
> >       * testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d: Likewise.
> >       * testsuite/ld-ifunc/ifunc-2-x86-64-now.d: Likewise.
> >       * testsuite/ld-ifunc/pr17154-x86-64.d: Likewise.
> >       * testsuite/ld-x86-64/bnd-branch-1-now.d: Likewise.
> >       * testsuite/ld-x86-64/bnd-ifunc-1-now.d: Likewise.
> >       * testsuite/ld-x86-64/bnd-ifunc-2-now.d: Likewise.
> >       * testsuite/ld-x86-64/bnd-ifunc-2.d: Likewise.
> >       * testsuite/ld-x86-64/bnd-plt-1-now.d: Likewise.
> >       * testsuite/ld-x86-64/bnd-plt-1.d: Likewise.
> >       * testsuite/ld-x86-64/ibt-plt-2a-x32.d: Likewise.
> >       * testsuite/ld-x86-64/ibt-plt-2a.d: Likewise.
> >       * testsuite/ld-x86-64/ibt-plt-3a-x32.d: Likewise.
> >       * testsuite/ld-x86-64/ibt-plt-3a.d: Likewise.
> >       * testsuite/ld-x86-64/ilp32-4.d: Likewise.
> >       * testsuite/ld-x86-64/load1c.d: Likewise.
> >       * testsuite/ld-x86-64/load1d.d: Likewise.
> >       * testsuite/ld-x86-64/pr13082-2b.d: Likewise.
> >       * testsuite/ld-x86-64/pr14207.d: Likewise.
> >       * testsuite/ld-x86-64/pr18176.d: Likewise.
> >       * testsuite/ld-x86-64/pr19162.d: Likewise.
> >       * testsuite/ld-x86-64/pr19636-2d.d: Likewise.
> >       * testsuite/ld-x86-64/pr19636-2l.d: Likewise.
> >       * testsuite/ld-x86-64/pr20253-1d.d: Likewise.
> >       * testsuite/ld-x86-64/pr20253-1f.d: Likewise.
> >       * testsuite/ld-x86-64/pr20253-1j.d: Likewise.
> >       * testsuite/ld-x86-64/pr20253-1l.d: Likewise.
> >       * testsuite/ld-x86-64/report-reloc-1-x32.d: Likewise.
> >       * testsuite/ld-x86-64/report-reloc-1.d: Likewise.
> >       * testsuite/ld-x86-64/export-class.exp (x86_64_export_class_test):
> >       Pass $NO_DT_RELR_LDFLAGS to linker.
> >       * testsuite/ld-x86-64/x86-64.exp: Pass $NO_DT_RELR_LDFLAGS to
> >       linker for some tests.
> >---
> > binutils/testsuite/lib/binutils-common.exp    |  1 +
> > ld/testsuite/config/default.exp               | 16 +++++
> > ld/testsuite/ld-elf/shared.exp                |  3 +-
> > ld/testsuite/ld-i386/export-class.exp         |  2 +-
> > ld/testsuite/ld-i386/i386.exp                 | 20 ++++--
> > ld/testsuite/ld-i386/ibt-plt-2a.d             |  2 +-
> > ld/testsuite/ld-i386/ibt-plt-3a.d             |  2 +-
> > ld/testsuite/ld-i386/ibt-plt-3c.d             |  2 +-
> > ld/testsuite/ld-i386/report-reloc-1.d         |  2 +-
> > ld/testsuite/ld-ifunc/ifunc-2-i386-now.d      |  2 +-
> > .../ld-ifunc/ifunc-2-local-i386-now.d         |  2 +-
> > .../ld-ifunc/ifunc-2-local-x86-64-now.d       |  2 +-
> > ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d    |  2 +-
> > ld/testsuite/ld-ifunc/pr17154-x86-64-now.d    |  2 +-
> > ld/testsuite/ld-ifunc/pr17154-x86-64.d        |  2 +-
> > ld/testsuite/ld-x86-64/bnd-branch-1-now.d     |  2 +-
> > ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d      |  2 +-
> > ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d      |  2 +-
> > ld/testsuite/ld-x86-64/bnd-ifunc-2.d          |  2 +-
> > ld/testsuite/ld-x86-64/bnd-plt-1-now.d        |  2 +-
> > ld/testsuite/ld-x86-64/bnd-plt-1.d            |  2 +-
> > ld/testsuite/ld-x86-64/export-class.exp       |  3 +-
> > ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d       |  2 +-
> > ld/testsuite/ld-x86-64/ibt-plt-2a.d           |  2 +-
> > ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d       |  2 +-
> > ld/testsuite/ld-x86-64/ibt-plt-3a.d           |  2 +-
> > ld/testsuite/ld-x86-64/ilp32-4.d              |  2 +-
> > ld/testsuite/ld-x86-64/load1c.d               |  2 +-
> > ld/testsuite/ld-x86-64/load1d.d               |  2 +-
> > ld/testsuite/ld-x86-64/pr13082-2b.d           |  2 +-
> > ld/testsuite/ld-x86-64/pr14207.d              |  2 +-
> > ld/testsuite/ld-x86-64/pr18176.d              |  2 +-
> > ld/testsuite/ld-x86-64/pr19162.d              |  2 +-
> > ld/testsuite/ld-x86-64/pr19636-2d.d           |  2 +-
> > ld/testsuite/ld-x86-64/pr19636-2l.d           |  2 +-
> > ld/testsuite/ld-x86-64/pr20253-1d.d           |  2 +-
> > ld/testsuite/ld-x86-64/pr20253-1f.d           |  2 +-
> > ld/testsuite/ld-x86-64/pr20253-1j.d           |  2 +-
> > ld/testsuite/ld-x86-64/pr20253-1l.d           |  2 +-
> > ld/testsuite/ld-x86-64/report-reloc-1-x32.d   |  2 +-
> > ld/testsuite/ld-x86-64/report-reloc-1.d       |  2 +-
> > ld/testsuite/ld-x86-64/x86-64.exp             | 65 ++++++++++++-------
> > 42 files changed, 114 insertions(+), 66 deletions(-)
> >
> >diff --git a/binutils/testsuite/lib/binutils-common.exp b/binutils/testsuite/lib/binutils-common.exp
> >index 0e0ba8e5aee..88fdc1a71c7 100644
> >--- a/binutils/testsuite/lib/binutils-common.exp
> >+++ b/binutils/testsuite/lib/binutils-common.exp
> >@@ -855,6 +855,7 @@ proc run_dump_test { name {extra_options {}} } {
> >     global ELFEDIT ELFEDITFLAGS LD LDFLAGS NM NMFLAGS OBJCOPY OBJCOPYFLAGS
> >     global OBJDUMP OBJDUMPFLAGS READELF READELFFLAGS STRIP STRIPFLAGS
> >     global copyfile env runtests srcdir subdir verbose
> >+    global DT_RELR_LDFLAGS NO_DT_RELR_LDFLAGS
> >
> >     if [string match "*/*" $name] {
> >       set file $name
> >diff --git a/ld/testsuite/config/default.exp b/ld/testsuite/config/default.exp
> >index c988d5d2924..52e75048ede 100644
> >--- a/ld/testsuite/config/default.exp
> >+++ b/ld/testsuite/config/default.exp
> >@@ -313,6 +313,22 @@ if ![info exists LDFLAGS] then {
> >     set LDFLAGS {}
> > }
> >
> >+if { ![info exists DT_RELR_LDFLAGS] } then {
> >+    set DT_RELR_LDFLAGS "-z pack-relative-relocs"
> >+}
>
> >+if { ![info exists DT_RELR_CC_LDFLAGS] } then {
> >+    set DT_RELR_CC_LDFLAGS "-Wl,-z,pack-relative-relocs"
> >+}
> >+
>
> GCC driver supports -z for a very long time (at least >=4.1.2),
> so -Wl,-z, may be combined with the preceding -z.

This won't hurt and is more flexible.

> >+if { ![info exists NO_DT_RELR_LDFLAGS] } then {
> >+    set NO_DT_RELR_LDFLAGS "-z nopack-relative-relocs"
> >+}
> >+
> >+if { ![info exists NO_DT_RELR_CC_LDFLAGS] } then {
> >+    set NO_DT_RELR_CC_LDFLAGS "-Wl,-z,nopack-relative-relocs"
> >+}
> >+
> > # Set LD_CLASS to "64bit" for a 64-bit *host* linker.
> > if { ![info exists LD_CLASS] } then {
> >     set REAL_LD [findfile $base_dir/.libs/ld-new .libs/ld-new $LD [transform ld]]
> >diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
> >index cb3b8c15cfc..1381544e6f8 100644
> >--- a/ld/testsuite/ld-elf/shared.exp
> >+++ b/ld/testsuite/ld-elf/shared.exp
> >@@ -452,7 +452,8 @@ setup_xfail mips*-*-* bfin-*-*
> > clear_xfail bfin-*-linux*
> > run_ld_link_tests [list \
> >     [list "-Bsymbolic-functions" \
> >-      "-shared -Bsymbolic-functions" "" "$AFLAGS_PIC" \
> >+      "-shared -Bsymbolic-functions $NO_DT_RELR_LDFLAGS" \
> >+      "" "$AFLAGS_PIC" \
> >       {symbolic-func.s} {{readelf {-r --wide} symbolic-func.r}} \
> >       "symbolic-func.so"] \
> > ]
> >diff --git a/ld/testsuite/ld-i386/export-class.exp b/ld/testsuite/ld-i386/export-class.exp
> >index 47b2c0f0056..04bc6a0d836 100644
> >--- a/ld/testsuite/ld-i386/export-class.exp
> >+++ b/ld/testsuite/ld-i386/export-class.exp
> >@@ -74,7 +74,7 @@ run_ld_link_tests [list \
> > run_ld_link_tests [list \
> >     [list \
> >       "$testname (final shared object)" \
> >-      "-shared -Tdata=0x12340000 tmpdir/i386-export-class-ref-r.o tmpdir/i386-export-class-lib.so" "" \
> >+      "-shared $NO_DT_RELR_LDFLAGS -Tdata=0x12340000 tmpdir/i386-export-class-ref-r.o tmpdir/i386-export-class-lib.so" "" \
> >       "" \
> >       { ../ld-elf/export-class-dep.s ../ld-elf/export-class-def.s } \
> >       { \
> >diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
> >index 3ed6e42e78f..c2d8d8268c3 100644
> >--- a/ld/testsuite/ld-i386/i386.exp
> >+++ b/ld/testsuite/ld-i386/i386.exp
> >@@ -177,12 +177,6 @@ set i386tests {
> >      {{readelf -Ssrl tlsbindesc.rd} {objdump -drj.text tlsbindesc.dd}
> >       {objdump -sj.got tlsbindesc.sd} {objdump -sj.tdata tlsbindesc.td}}
> >       "tlsbindesc"}
> >-    {"TLS -fno-pic -shared"
> >-     "-shared -melf_i386 --no-ld-generated-unwind-info -z notext \
> >-      -z noseparate-code --hash-style=sysv" ""
> >-     "--32" {tlsnopic1.s tlsnopic2.s}
> >-     {{readelf -Ssrl tlsnopic.rd} {objdump -drj.text tlsnopic.dd}
> >-      {objdump -sj.got tlsnopic.sd}} "libtlsnopic.so"}
> >     {"TLS with global dynamic and descriptors"
> >      "-shared -melf_i386 --no-ld-generated-unwind-info \
> >       -z noseparate-code --hash-style=sysv" ""
> >@@ -293,6 +287,20 @@ iamcu_tests
> >
> > run_ld_link_tests $i386tests
> >
> >+run_ld_link_tests [list \
> >+    [list \
> >+      "TLS -fno-pic -shared" \
> >+      "-shared -melf_i386 --no-ld-generated-unwind-info -z notext \
> >+       -z noseparate-code --hash-style=sysv $NO_DT_RELR_LDFLAGS" \
> >+      "" "--32" \
> >+      {tlsnopic1.s tlsnopic2.s} \
> >+      {{readelf -Ssrl tlsnopic.rd} \
> >+       {objdump -drj.text tlsnopic.dd} \
> >+       {objdump -sj.got tlsnopic.sd}} \
> >+      "libtlsnopic.so" \
> >+    ] \
> >+]
> >+
> > run_dump_test "abs"
> > run_dump_test "pcrel8"
> > run_dump_test "pcrel16"
> >diff --git a/ld/testsuite/ld-i386/ibt-plt-2a.d b/ld/testsuite/ld-i386/ibt-plt-2a.d
> >index 42aa2ce7410..98b6fb9a5aa 100644
> >--- a/ld/testsuite/ld-i386/ibt-plt-2a.d
> >+++ b/ld/testsuite/ld-i386/ibt-plt-2a.d
> >@@ -1,6 +1,6 @@
> > #source: ibt-plt-2.s
> > #as: --32
> >-#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code
> >+#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-i386/ibt-plt-3a.d b/ld/testsuite/ld-i386/ibt-plt-3a.d
> >index b357a74a33b..91f2023db35 100644
> >--- a/ld/testsuite/ld-i386/ibt-plt-3a.d
> >+++ b/ld/testsuite/ld-i386/ibt-plt-3a.d
> >@@ -1,6 +1,6 @@
> > #source: ibt-plt-3.s
> > #as: --32
> >-#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code
> >+#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-i386/ibt-plt-3c.d b/ld/testsuite/ld-i386/ibt-plt-3c.d
> >index b357a74a33b..91f2023db35 100644
> >--- a/ld/testsuite/ld-i386/ibt-plt-3c.d
> >+++ b/ld/testsuite/ld-i386/ibt-plt-3c.d
> >@@ -1,6 +1,6 @@
> > #source: ibt-plt-3.s
> > #as: --32
> >-#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code
> >+#ld: -shared -m elf_i386 -z ibtplt --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-i386/report-reloc-1.d b/ld/testsuite/ld-i386/report-reloc-1.d
> >index 51fbbd8d105..162161592a1 100644
> >--- a/ld/testsuite/ld-i386/report-reloc-1.d
> >+++ b/ld/testsuite/ld-i386/report-reloc-1.d
> >@@ -1,6 +1,6 @@
> > #source: report-reloc-1.s
> > #as: --32
> >-#ld: -pie -melf_i386 -z report-relative-reloc
> >+#ld: -pie -melf_i386 -z report-relative-reloc $NO_DT_RELR_LDFLAGS
> > #warning_output: report-reloc-1.l
> > #readelf: -r --wide
> >
> >diff --git a/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d b/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d
> >index 0d3f7b80d06..aae24b2809d 100644
> >--- a/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d
> >+++ b/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d
> >@@ -1,5 +1,5 @@
> > #source: ifunc-2-i386.s
> >-#ld: -z now -m elf_i386 -shared --hash-style=sysv -z noseparate-code
> >+#ld: -z now -m elf_i386 -shared --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #as: --32
> > #objdump: -dw
> > #target: x86_64-*-* i?86-*-*
> >diff --git a/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d b/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d
> >index 48d2084d38f..86083c12a08 100644
> >--- a/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d
> >+++ b/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d
> >@@ -1,5 +1,5 @@
> > #source: ifunc-2-local-i386.s
> >-#ld: -z now -m elf_i386 -shared --hash-style=sysv -z noseparate-code
> >+#ld: -z now -m elf_i386 -shared --hash-style=sysv -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #as: --32
> > #objdump: -dw
> > #target: x86_64-*-* i?86-*-*
> >diff --git a/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d b/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d
> >index 14866a8f6cc..be3da08e12b 100644
> >--- a/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d
> >+++ b/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d
> >@@ -1,6 +1,6 @@
> > #source: ifunc-2-local-x86-64.s
> > #as: --64
> >-#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> > #target: x86_64-*-*
> >
> >diff --git a/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d b/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d
> >index 1cd60941ac0..b504f9adedd 100644
> >--- a/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d
> >+++ b/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d
> >@@ -1,6 +1,6 @@
> > #source: ifunc-2-x86-64.s
> > #as: --64
> >-#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> > #target: x86_64-*-*
> >
> >diff --git a/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d b/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d
> >index 4cc1dc206d5..f6920272b63 100644
> >--- a/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d
> >+++ b/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d
> >@@ -1,6 +1,6 @@
> > #source: pr17154-x86.s
> > #as: --64
> >-#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> > #target: x86_64-*-*
> >
> >diff --git a/ld/testsuite/ld-ifunc/pr17154-x86-64.d b/ld/testsuite/ld-ifunc/pr17154-x86-64.d
> >index 9fb23d410e3..90918426ee5 100644
> >--- a/ld/testsuite/ld-ifunc/pr17154-x86-64.d
> >+++ b/ld/testsuite/ld-ifunc/pr17154-x86-64.d
> >@@ -1,6 +1,6 @@
> > #source: pr17154-x86.s
> > #as: --64
> >-#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> > #target: x86_64-*-*
> >
> >diff --git a/ld/testsuite/ld-x86-64/bnd-branch-1-now.d b/ld/testsuite/ld-x86-64/bnd-branch-1-now.d
> >index b7bc4e526cc..b1bcea3cf4c 100644
> >--- a/ld/testsuite/ld-x86-64/bnd-branch-1-now.d
> >+++ b/ld/testsuite/ld-x86-64/bnd-branch-1-now.d
> >@@ -1,6 +1,6 @@
> > #source: bnd-branch-1.s -mx86-used-note=no
> > #as: --64
> >-#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -z now -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d b/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d
> >index 15ecfe1cc50..86ba30a46d5 100644
> >--- a/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d
> >+++ b/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d
> >@@ -1,6 +1,6 @@
> > #source: bnd-ifunc-1.s
> > #as: --64 -madd-bnd-prefix -mx86-used-note=no
> >-#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d b/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d
> >index 211d72d2335..fa7ec07aaf0 100644
> >--- a/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d
> >+++ b/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d
> >@@ -1,6 +1,6 @@
> > #source: bnd-ifunc-2.s
> > #as: --64 -madd-bnd-prefix -mx86-used-note=no
> >-#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/bnd-ifunc-2.d b/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
> >index f80ba15aa35..36534b14feb 100644
> >--- a/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
> >+++ b/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
> >@@ -1,5 +1,5 @@
> > #as: --64 -madd-bnd-prefix -mx86-used-note=no
> >-#ld: -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > #...
> >diff --git a/ld/testsuite/ld-x86-64/bnd-plt-1-now.d b/ld/testsuite/ld-x86-64/bnd-plt-1-now.d
> >index 24e28210a0a..47289a04f43 100644
> >--- a/ld/testsuite/ld-x86-64/bnd-plt-1-now.d
> >+++ b/ld/testsuite/ld-x86-64/bnd-plt-1-now.d
> >@@ -1,6 +1,6 @@
> > #source: bnd-branch-1.s
> > #as: --64 -mx86-used-note=no
> >-#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -z now -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/bnd-plt-1.d b/ld/testsuite/ld-x86-64/bnd-plt-1.d
> >index 0df32555c18..f047da897ce 100644
> >--- a/ld/testsuite/ld-x86-64/bnd-plt-1.d
> >+++ b/ld/testsuite/ld-x86-64/bnd-plt-1.d
> >@@ -1,6 +1,6 @@
> > #source: bnd-branch-1.s
> > #as: --64 -mx86-used-note=no
> >-#ld: -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -shared -melf_x86_64 -z bndplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/export-class.exp b/ld/testsuite/ld-x86-64/export-class.exp
> >index 26896d1ca87..14c2d240fac 100644
> >--- a/ld/testsuite/ld-x86-64/export-class.exp
> >+++ b/ld/testsuite/ld-x86-64/export-class.exp
> >@@ -31,6 +31,7 @@ if { ![istarget x86_64*-*-linux*] } {
> > }
> >
> > proc x86_64_export_class_test { abi flag emul } {
> >+    global NO_DT_RELR_LDFLAGS
> >
> >     set testname "x86-64 $abi symbol export class test"
> >
> >@@ -75,7 +76,7 @@ proc x86_64_export_class_test { abi flag emul } {
> >     run_ld_link_tests [list \
> >       [list \
> >           "$testname (final shared object)" \
> >-          "$LDFLAGS -shared -Tdata=0x12340000 tmpdir/x86-64-$abi-export-class-ref-r.o tmpdir/x86-64-$abi-export-class-lib.so" "" \
> >+          "$LDFLAGS $NO_DT_RELR_LDFLAGS -shared -Tdata=0x12340000 tmpdir/x86-64-$abi-export-class-ref-r.o tmpdir/x86-64-$abi-export-class-lib.so" "" \
> >           "$AFLAGS" \
> >           { ../ld-elf/export-class-dep.s ../ld-elf/export-class-def.s } \
> >           [list \
> >diff --git a/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d
> >index a19cece98e8..23e31e62f55 100644
> >--- a/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d
> >+++ b/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d
> >@@ -1,6 +1,6 @@
> > #source: ibt-plt-2.s
> > #as: --x32
> >-#ld: -shared -m elf32_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -shared -m elf32_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/ibt-plt-2a.d b/ld/testsuite/ld-x86-64/ibt-plt-2a.d
> >index 92785929092..adbbf62e84d 100644
> >--- a/ld/testsuite/ld-x86-64/ibt-plt-2a.d
> >+++ b/ld/testsuite/ld-x86-64/ibt-plt-2a.d
> >@@ -1,6 +1,6 @@
> > #source: ibt-plt-2.s
> > #as: --64 -defsym __64_bit__=1
> >-#ld: -shared -m elf_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -shared -m elf_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d
> >index d6f8bb3afbe..f52b1cc796f 100644
> >--- a/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d
> >+++ b/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d
> >@@ -1,6 +1,6 @@
> > #source: ibt-plt-3.s
> > #as: --x32
> >-#ld: -shared -m elf32_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -shared -m elf32_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/ibt-plt-3a.d b/ld/testsuite/ld-x86-64/ibt-plt-3a.d
> >index 9c15ed4f928..8bd8851ea73 100644
> >--- a/ld/testsuite/ld-x86-64/ibt-plt-3a.d
> >+++ b/ld/testsuite/ld-x86-64/ibt-plt-3a.d
> >@@ -1,6 +1,6 @@
> > #source: ibt-plt-3.s
> > #as: --64 -defsym __64_bit__=1
> >-#ld: -shared -m elf_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -shared -m elf_x86_64 -z ibtplt --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/ilp32-4.d b/ld/testsuite/ld-x86-64/ilp32-4.d
> >index 34be012056e..ad5c9cdf858 100644
> >--- a/ld/testsuite/ld-x86-64/ilp32-4.d
> >+++ b/ld/testsuite/ld-x86-64/ilp32-4.d
> >@@ -1,5 +1,5 @@
> > #as: --x32
> >-#ld: -m elf32_x86_64 -shared --no-ld-generated-unwind-info --hash-style=sysv
> >+#ld: -m elf32_x86_64 -shared --no-ld-generated-unwind-info --hash-style=sysv $NO_DT_RELR_LDFLAGS
> > #readelf: -d -S --wide
> > #target: x86_64-*-linux*
> >
> >diff --git a/ld/testsuite/ld-x86-64/load1c.d b/ld/testsuite/ld-x86-64/load1c.d
> >index db9c69fadbf..7404c7093b4 100644
> >--- a/ld/testsuite/ld-x86-64/load1c.d
> >+++ b/ld/testsuite/ld-x86-64/load1c.d
> >@@ -1,6 +1,6 @@
> > #source: load1.s
> > #as: --64
> >-#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/load1d.d b/ld/testsuite/ld-x86-64/load1d.d
> >index 7ccae532f27..1b474a375c7 100644
> >--- a/ld/testsuite/ld-x86-64/load1d.d
> >+++ b/ld/testsuite/ld-x86-64/load1d.d
> >@@ -1,6 +1,6 @@
> > #source: load1.s
> > #as: --x32
> >-#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/pr13082-2b.d b/ld/testsuite/ld-x86-64/pr13082-2b.d
> >index c218eafe34c..71c44fc0ee5 100644
> >--- a/ld/testsuite/ld-x86-64/pr13082-2b.d
> >+++ b/ld/testsuite/ld-x86-64/pr13082-2b.d
> >@@ -1,7 +1,7 @@
> > #source: pr13082-2.s
> > #name: PR ld/13082-2 (b)
> > #as: --x32
> >-#ld: -pie -melf32_x86_64
> >+#ld: -pie -melf32_x86_64 $NO_DT_RELR_LDFLAGS
> > #readelf: -r --wide
> >
> > Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entry:
> >diff --git a/ld/testsuite/ld-x86-64/pr14207.d b/ld/testsuite/ld-x86-64/pr14207.d
> >index f330600b916..e3af36146c6 100644
> >--- a/ld/testsuite/ld-x86-64/pr14207.d
> >+++ b/ld/testsuite/ld-x86-64/pr14207.d
> >@@ -1,6 +1,6 @@
> > #name: PR ld/14207
> > #as: --64
> >-#ld: -melf_x86_64 -shared -z relro -z now --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -melf_x86_64 -shared -z relro -z now --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #readelf: -l --wide
> > #target: x86_64-*-linux*
> >
> >diff --git a/ld/testsuite/ld-x86-64/pr18176.d b/ld/testsuite/ld-x86-64/pr18176.d
> >index 4e3ad9ff08d..a99ff15ac6b 100644
> >--- a/ld/testsuite/ld-x86-64/pr18176.d
> >+++ b/ld/testsuite/ld-x86-64/pr18176.d
> >@@ -1,6 +1,6 @@
> > #name: PR ld/18176
> > #as: --64
> >-#ld: -melf_x86_64 -shared -z relro -T pr18176.t -z max-page-size=0x200000 -z common-page-size=0x1000
> >+#ld: -melf_x86_64 -shared -z relro -T pr18176.t -z max-page-size=0x200000 -z common-page-size=0x1000 $NO_DT_RELR_LDFLAGS
> > #readelf: -l --wide
> > #target: x86_64-*-linux*
> >
> >diff --git a/ld/testsuite/ld-x86-64/pr19162.d b/ld/testsuite/ld-x86-64/pr19162.d
> >index 2d51dabe729..f458853d8e5 100644
> >--- a/ld/testsuite/ld-x86-64/pr19162.d
> >+++ b/ld/testsuite/ld-x86-64/pr19162.d
> >@@ -1,7 +1,7 @@
> > #source: pr19162a.s
> > #source: pr19162b.s
> > #as: --64
> >-#ld: -melf_x86_64 -shared -z noseparate-code -z max-page-size=0x200000 -z common-page-size=0x1000 --hash-style=sysv
> >+#ld: -melf_x86_64 -shared -z noseparate-code -z max-page-size=0x200000 -z common-page-size=0x1000 --hash-style=sysv $NO_DT_RELR_LDFLAGS
> > #readelf: -l --wide
> > #target: x86_64-*-linux*
> >
> >diff --git a/ld/testsuite/ld-x86-64/pr19636-2d.d b/ld/testsuite/ld-x86-64/pr19636-2d.d
> >index 3bd33a9a915..092992be9d4 100644
> >--- a/ld/testsuite/ld-x86-64/pr19636-2d.d
> >+++ b/ld/testsuite/ld-x86-64/pr19636-2d.d
> >@@ -1,6 +1,6 @@
> > #source: pr19636-2.s
> > #as: --64 -mrelax-relocations=no
> >-#ld: -pie -m elf_x86_64 --no-dynamic-linker --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -pie -m elf_x86_64 --no-dynamic-linker --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/pr19636-2l.d b/ld/testsuite/ld-x86-64/pr19636-2l.d
> >index 1b894b3e97c..8c23c0b7411 100644
> >--- a/ld/testsuite/ld-x86-64/pr19636-2l.d
> >+++ b/ld/testsuite/ld-x86-64/pr19636-2l.d
> >@@ -1,6 +1,6 @@
> > #source: pr19636-2.s
> > #as: --64 -mrelax-relocations=no
> >-#ld: -pie -m elf_x86_64 --no-dynamic-linker --hash-style=sysv -z dynamic-undefined-weak -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -pie -m elf_x86_64 --no-dynamic-linker --hash-style=sysv -z dynamic-undefined-weak -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> > #warning: -z dynamic-undefined-weak ignored
> >
> >diff --git a/ld/testsuite/ld-x86-64/pr20253-1d.d b/ld/testsuite/ld-x86-64/pr20253-1d.d
> >index f9f03ba8403..057577bdc57 100644
> >--- a/ld/testsuite/ld-x86-64/pr20253-1d.d
> >+++ b/ld/testsuite/ld-x86-64/pr20253-1d.d
> >@@ -1,6 +1,6 @@
> > #source: pr20253-1.s
> > #as: --64
> >-#ld: -pie -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -pie -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/pr20253-1f.d b/ld/testsuite/ld-x86-64/pr20253-1f.d
> >index 6666bcaf147..479db8202e8 100644
> >--- a/ld/testsuite/ld-x86-64/pr20253-1f.d
> >+++ b/ld/testsuite/ld-x86-64/pr20253-1f.d
> >@@ -1,6 +1,6 @@
> > #source: pr20253-1.s
> > #as: --64
> >-#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/pr20253-1j.d b/ld/testsuite/ld-x86-64/pr20253-1j.d
> >index 88c9715ad75..20176a2d357 100644
> >--- a/ld/testsuite/ld-x86-64/pr20253-1j.d
> >+++ b/ld/testsuite/ld-x86-64/pr20253-1j.d
> >@@ -1,6 +1,6 @@
> > #source: pr20253-1.s
> > #as: --x32
> >-#ld: -pie -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -pie -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/pr20253-1l.d b/ld/testsuite/ld-x86-64/pr20253-1l.d
> >index 7428a721b16..4b179077dec 100644
> >--- a/ld/testsuite/ld-x86-64/pr20253-1l.d
> >+++ b/ld/testsuite/ld-x86-64/pr20253-1l.d
> >@@ -1,6 +1,6 @@
> > #source: pr20253-1.s
> > #as: --x32
> >-#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
> >+#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
> > #objdump: -dw
> >
> > .*: +file format .*
> >diff --git a/ld/testsuite/ld-x86-64/report-reloc-1-x32.d b/ld/testsuite/ld-x86-64/report-reloc-1-x32.d
> >index c66f956c473..63fe7b1bb8a 100644
> >--- a/ld/testsuite/ld-x86-64/report-reloc-1-x32.d
> >+++ b/ld/testsuite/ld-x86-64/report-reloc-1-x32.d
> >@@ -1,6 +1,6 @@
> > #source: report-reloc-1.s
> > #as: --x32
> >-#ld: -pie -melf32_x86_64 -z report-relative-reloc
> >+#ld: -pie -melf32_x86_64 -z report-relative-reloc $NO_DT_RELR_LDFLAGS
> > #warning_output: report-reloc-1.l
> > #readelf: -r --wide
> >
> >diff --git a/ld/testsuite/ld-x86-64/report-reloc-1.d b/ld/testsuite/ld-x86-64/report-reloc-1.d
> >index 1b5f91fdd3f..69f164c9434 100644
> >--- a/ld/testsuite/ld-x86-64/report-reloc-1.d
> >+++ b/ld/testsuite/ld-x86-64/report-reloc-1.d
> >@@ -1,6 +1,6 @@
> > #source: report-reloc-1.s
> > #as: --64
> >-#ld: -pie -melf_x86_64 -z report-relative-reloc
> >+#ld: -pie -melf_x86_64 -z report-relative-reloc $NO_DT_RELR_LDFLAGS
> > #warning_output: report-reloc-1.l
> > #readelf: -r --wide
> >
> >diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
> >index c100879397e..b4048128057 100644
> >--- a/ld/testsuite/ld-x86-64/x86-64.exp
> >+++ b/ld/testsuite/ld-x86-64/x86-64.exp
> >@@ -45,28 +45,6 @@ set x86_64tests {
> >     {"basic PLT generation"
> >      "-melf_x86_64 tmpdir/libpltlib.so" "" "--64" {plt.s}
> >      {{objdump -drj.plt plt.pd}} "plt"}
> >-    {"TLS -fpic -shared transitions"
> >-     "-shared -melf_x86_64 --no-ld-generated-unwind-info \
> >-      -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv" ""
> >-     "--64" {tlspic1.s tlspic2.s}
> >-     {{readelf -WSsrl tlspic.rd} {objdump -drj.text\ -Mintel64 tlspic.dd}
> >-      {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
> >-      "libtlspic.so"}
> >-    {"TLS -fpic -shared transitions with r15 as GOT base"
> >-     "-shared -melf_x86_64 --no-ld-generated-unwind-info \
> >-      -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv" ""
> >-     "--64 -mrelax-relocations=yes"
> >-     {tlspic3.s tlspic2.s}
> >-     {{readelf -WSsrl tlspic2.rd} {objdump -drj.text\ -Mintel64 tlspic2.dd}
> >-      {objdump -sj.got tlspic2.sd} {objdump -sj.tdata tlspic2.td}}
> >-      "libtlspic2.so"}
> >-    {"TLS descriptor -fpic -shared transitions"
> >-     "-shared -melf_x86_64 --no-ld-generated-unwind-info \
> >-      -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv" ""
> >-     "--64" {tlsdesc.s tlspic2.s}
> >-     {{readelf -WSsrld tlsdesc.rd} {objdump -drj.text tlsdesc.dd}
> >-      {objdump "-s -j.got -j.got.plt" tlsdesc.sd} {objdump -sj.tdata tlsdesc.td}
> >-      {objdump -drj.plt tlsdesc.pd}} "libtlsdesc.so"}
> >     {"Helper shared library" "-shared -melf_x86_64" ""
> >      "--64" {tlslib.s} {} "libtlslib.so"}
> >     {"TLS -fpic and -fno-pic exec transitions"
> >@@ -240,6 +218,49 @@ set x86_64tests {
> >
> > run_ld_link_tests $x86_64tests
> >
> >+run_ld_link_tests [list \
> >+    [list \
> >+      "TLS -fpic -shared transitions" \
> >+      "-shared -melf_x86_64 --no-ld-generated-unwind-info \
> >+       -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv \
> >+       $NO_DT_RELR_LDFLAGS" \
> >+      "" "--64" \
> >+      {tlspic1.s tlspic2.s} \
> >+      {{readelf -WSsrl tlspic.rd} \
> >+       {objdump {-drj.text -Mintel64} tlspic.dd} \
> >+       {objdump -sj.got tlspic.sd} \
> >+       {objdump -sj.tdata tlspic.td}} \
> >+      "libtlspic.so" \
> >+    ] \
> >+    [list \
> >+      "TLS -fpic -shared transitions with r15 as GOT base" \
> >+      "-shared -melf_x86_64 --no-ld-generated-unwind-info \
> >+       -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv \
> >+       $NO_DT_RELR_LDFLAGS" \
> >+       "" "--64 -mrelax-relocations=yes" \
> >+      {tlspic3.s tlspic2.s} \
> >+      {{readelf -WSsrl tlspic2.rd} \
> >+       {objdump {-drj.text -Mintel64} tlspic2.dd} \
> >+       {objdump -sj.got tlspic2.sd} \
> >+       {objdump -sj.tdata tlspic2.td}} \
> >+      "libtlspic2.so" \
> >+    ] \
> >+    [list \
> >+      "TLS descriptor -fpic -shared transitions" \
> >+      "-shared -melf_x86_64 --no-ld-generated-unwind-info \
> >+       -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv \
> >+       $NO_DT_RELR_LDFLAGS" \
> >+      "" "--64" \
> >+      {tlsdesc.s tlspic2.s} \
> >+      {{readelf -WSsrld tlsdesc.rd} \
> >+       {objdump -drj.text tlsdesc.dd} \
> >+       {objdump {-s -j.got -j.got.plt} tlsdesc.sd} \
> >+       {objdump -sj.tdata tlsdesc.td} \
> >+       {objdump -drj.plt tlsdesc.pd}} \
> >+       "libtlsdesc.so" \
> >+    ] \
> >+]
> >+
> > set test_name "Mixed x86_64 and i386 input test 1"
> > set test mixed1
> > if { ![ld_link $ld tmpdir/$test "-m$emul tmpdir/${test}a.o tmpdir/${test}b.o"] } {
> >--
> >2.33.1
> >



-- 
H.J.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 0/10] ld: Implement DT_RELR for x86
  2022-01-08  1:55       ` H.J. Lu
@ 2022-01-08 18:30         ` H.J. Lu
  0 siblings, 0 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-08 18:30 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Fangrui Song, GNU C Library, Binutils

On Fri, Jan 7, 2022 at 5:55 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Fri, Jan 7, 2022 at 5:31 PM Fangrui Song <i@maskray.me> wrote:
> >
> > On 2022-01-07, H.J. Lu via Binutils wrote:
> > >On Fri, Jan 7, 2022 at 3:46 PM Fangrui Song <maskray@google.com> wrote:
> > >>
> > >> On 2022-01-07, H.J. Lu via Libc-alpha wrote:
> > >> >Hi Nick,
> > >> >
> > >> >I'd like to enable DT_RELR for x86 in binutils 2.38.
> > >> >
> > >> >
> > >> >H.J.
> > >> >---
> > >>
> > >> Thanks for the patch!
> > >>
> > >> Is the Clang crash
> > >> https://sourceware.org/pipermail/libc-alpha/2022-January/134992.html
> > >> fixed now?
> > >>
> > >
> > >It should be fixed.  Please try my current DT_RELR branch.
> >
> > Thanks. It works.
> >
> > % rm /tmp/out/custom1/clang
> > % ninja -C /tmp/out/custom1/clang -v  # find the linker command line
> > % <linker-command-line> -Wl,--reproduce=/tmp/clang-relassert.tar
> > % cd /tmp && tar xf clang-relassert.tar && cd clang-relassert
> > # Remove --chroot from response.txt
> >
> > # Managed to compile a file with the linked clang
> > % ~/Dev/binutils-gdb/out/release/ld/ld-new -z pack-relative-relocs @response.txt -o bfd.relr
> > % LD_LIBRARY_PATH=/tmp/glibc/lld/lib:/usr/lib/x86_64-linux-gnu /tmp/glibc/lld/lib/ld-linux-x86-64.so.2 ./bfd.relr -c /tmp/c/a.c -O2
> >
> >
> > There are still quite a few even-address R_X86_64_RELATIVE relocations.
> > Any idea why they are present?
>
> ld can generate R_X86_64_RELATIVE in elf_x86_64_finish_dynamic_symbol:
>
>      else if (bfd_link_pic (info)
>                && SYMBOL_REFERENCES_LOCAL_P (info, h))
>         {
>           if (!SYMBOL_DEFINED_NON_SHARED_P (h))
>             return false;
>           BFD_ASSERT((h->got.offset & 1) != 0);
>           rela.r_info = htab->r_info (0, R_X86_64_RELATIVE);
>           rela.r_addend = (h->root.u.def.value
>                            + h->root.u.def.section->output_section->vma
>                            + h->root.u.def.section->output_offset);
>           relative_reloc_name = "R_X86_64_RELATIVE";
>         }
>
> This case isn't handled yet.

Fixed in the v2 patch.

> >
> > % ~/Dev/binutils-gdb/out/release/binutils/readelf -r bfd.relr
> > ...
> > Relocation section '.rela.dyn' at offset 0x5fb400 contains 3133 entries:
> >    Offset          Info           Type           Sym. Value    Sym. Name + Addend
> > 000009902608  000000000008 R_X86_64_RELATIVE                    9281940
> > 000009902610  000000000008 R_X86_64_RELATIVE                    7a4d565
> > 000009902618  000000000008 R_X86_64_RELATIVE                    91acf98
> > ...
> > Relocation section '.relr.dyn' at offset 0x60f6e0 contains 19910 entries:
> >    535577 offsets
> > 0000000008f83f58
> > 0000000008f83f60
> > 0000000008f83f68
> > ...
> >
> > >
> > >> > 10/10 ld: Add glibc dependency for DT_RELR
> > >> >
> > >> > if (!glibc_bfd && startswith (a->vna_nodename, "GLIBC_2."))
> > >>
> > >> Thanks for adding the GLIBC_ABI_DT_RELR verneed only if GLIBC_2.* exists, this will make
> > >> musl/FreeBSD/NetBSD/etc happy.
> >
> > Does your DT_RELR patch have something like this?
> >
> > +    // Don't allow the section to shrink, otherwise the size of the section can
> > +    // oscillate infinitely. Trailing 1s do not decode to more relocations.
> > +    if (entries_.size() < old_size)
> > +      entries_.resize(old_size, 1);
>
>      if (dt_relr_bitmap_count > new_count)
>         {
>           /* Don't shrink the DT_RELR section size to avoid section
>              layout oscillation.  Instead, pad the DT_RELR bitmap with
>              1s which do not decode to more relocations.  */
>
>           htab->dt_relr_bitmap.count = dt_relr_bitmap_count;
>           count = dt_relr_bitmap_count - new_count;
>           for (i = 0; i < count; i++)
>             htab->dt_relr_bitmap.u.elf64[new_count + i] = 1;
>         }
>
>
> --
> H.J.



-- 
H.J.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 05/10] ld: Initial DT_RELR support
  2022-01-08  2:42     ` H.J. Lu
@ 2022-01-08 18:32       ` H.J. Lu
  0 siblings, 0 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-08 18:32 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils, GNU C Library

On Fri, Jan 7, 2022 at 6:42 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Fri, Jan 7, 2022 at 6:10 PM Fangrui Song <i@maskray.me> wrote:
> >
> > On 2022-01-07, H.J. Lu via Binutils wrote:
> > >Add a -z pack-relative-relocs option to enable DT_RELR and create a
> > >relr.dyn section for DT_RELR.
> > >
> > >-z pack-relative-relocs implies -z combreloc and --relax.  --no-relax
> > >and -z nocombreloc imply -z nopack-relative-relocs.
> > >
> > >-z pack-relative-relocs is chosen over the similar option in lld,
> > >--pack-dyn-relocs=relr, to implement a glibc binary lockout mechanism
> > >with a special glibc version symbol, to avoid random crashes of DT_RELR
> > >binaries with the existing glibc binaries.
> >
> > Why does --no-relax suppress  -z nopack-relative-relocs?
>
> -z nopack-relative-relocs uses the linker relaxation.  It is
> possible to do it with --no-relax.  But it requires a major change
> in the linker relaxation.
>

It turns out to be a simple change.  Fixed in the v2 patch.


H.J.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 09/10] ld: Add simple DT_RELR tests
  2022-01-08  8:37   ` Fangrui Song
@ 2022-01-08 18:33     ` H.J. Lu
  0 siblings, 0 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-08 18:33 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils, GNU C Library

On Sat, Jan 8, 2022 at 12:37 AM Fangrui Song <i@maskray.me> wrote:
>
> On 2022-01-07, H.J. Lu via Binutils wrote:
> >       * testsuite/ld-elf/dt-relr-1.s: New file.
> >       * testsuite/ld-elf/dt-relr-1a.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-1b.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-1c.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2.s: Likewise.
> >       * testsuite/ld-elf/dt-relr-2a.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2b.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2c.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2d.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2e.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2f.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2g.d: Likewise.
> >       * testsuite/ld-elf/dt-relr-2h.d: Likewise.
> >---
> > ld/testsuite/ld-elf/dt-relr-1.s  | 13 +++++++++++++
> > ld/testsuite/ld-elf/dt-relr-1a.d | 10 ++++++++++
> > ld/testsuite/ld-elf/dt-relr-1b.d |  9 +++++++++
> > ld/testsuite/ld-elf/dt-relr-1c.d |  9 +++++++++
> > ld/testsuite/ld-elf/dt-relr-2.s  | 20 ++++++++++++++++++++
> > ld/testsuite/ld-elf/dt-relr-2a.d | 10 ++++++++++
> > ld/testsuite/ld-elf/dt-relr-2b.d | 17 +++++++++++++++++
> > ld/testsuite/ld-elf/dt-relr-2c.d | 17 +++++++++++++++++
> > ld/testsuite/ld-elf/dt-relr-2d.d |  9 +++++++++
> > ld/testsuite/ld-elf/dt-relr-2e.d |  9 +++++++++
> > ld/testsuite/ld-elf/dt-relr-2f.d |  8 ++++++++
> > ld/testsuite/ld-elf/dt-relr-2g.d |  9 +++++++++
> > ld/testsuite/ld-elf/dt-relr-2h.d |  9 +++++++++
> > 13 files changed, 149 insertions(+)
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-1.s
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-1a.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-1b.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-1c.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2.s
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2a.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2b.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2c.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2d.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2e.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2f.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2g.d
> > create mode 100644 ld/testsuite/ld-elf/dt-relr-2h.d
> >
> >diff --git a/ld/testsuite/ld-elf/dt-relr-1.s b/ld/testsuite/ld-elf/dt-relr-1.s
> >new file mode 100644
> >index 00000000000..18486d3acb2
> >--- /dev/null
> >+++ b/ld/testsuite/ld-elf/dt-relr-1.s
> >@@ -0,0 +1,13 @@
> >+      .text
> >+      .p2align 3
> >+      .globl _start
> >+_start:
> >+      .byte 0
> >+
> >+      .data
> >+      .p2align 3
> >+      .globl data
> >+data:
> >+      .byte 0
> >+      //  Offset is not a multiple of 2.  Don't use DT_RELR.
> >+      .dc.a __ehdr_start + 10
>
> .data
> .balign 1
> .dc.a .data
>
> may be worth adding as a test.
>
> Currently R_X86_64_RELATIVE is used even if its r_offset is even.
> There is conservative but safe as it's difficult to ensure an input
> section's address is even when its alignment is 1.
>

Added to the v2 patch.

-- 
H.J.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 10/10] ld: Add glibc dependency for DT_RELR
  2022-01-08  8:19       ` Fangrui Song
@ 2022-01-08 18:37         ` H.J. Lu
  0 siblings, 0 replies; 31+ messages in thread
From: H.J. Lu @ 2022-01-08 18:37 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils, GNU C Library

On Sat, Jan 8, 2022 at 12:19 AM Fangrui Song <i@maskray.me> wrote:
>
> On 2022-01-07, H.J. Lu wrote:
> >On Fri, Jan 7, 2022 at 8:43 PM Fangrui Song <i@maskray.me> wrote:
> >>
> >> On 2022-01-07, H.J. Lu via Binutils wrote:
> >> >When DT_RELR is enabled, to avoid random run-time crash with older glibc
> >> >binaries without DT_RELR support, add a GLIBC_ABI_DT_RELR symbol version,
> >> >which is provided by glibc with DT_RELR support, dependency on the shared
> >> >C library if it provides a GLIBC_2.XX symbol version.
> >> >
> >> >bfd/
> >> >
> >> >       * elflink.c (elf_link_add_dt_relr_dependency): New function.
> >> >       (bfd_elf_size_dynamic_sections): Call
> >> >       elf_link_add_dt_relr_dependency if DT_RELR is enabled.
> >> >
> >> >ld/
> >> >
> >> >       * ld.texi: Mention GLIBC_ABI_DT_RELR in -z pack-relative-relocs
> >> >       entry.
> >> >       * testsuite/ld-elf/dt-relr-glibc-1.c: New file.
> >> >       * testsuite/ld-elf/dt-relr-glibc-1a.rd: Likewise.
> >> >       * testsuite/ld-elf/dt-relr-glibc-1b.rd: Likewise.
> >> >       * testsuite/ld-elf/dt-relr.exp: Likewise.
> >> >---
> >> > bfd/elflink.c                           | 86 +++++++++++++++++++++++++
> >> > ld/ld.texi                              |  4 +-
> >> > ld/testsuite/ld-elf/dt-relr-glibc-1.c   | 11 ++++
> >> > ld/testsuite/ld-elf/dt-relr-glibc-1a.rd |  4 ++
> >> > ld/testsuite/ld-elf/dt-relr-glibc-1b.rd |  7 ++
> >> > ld/testsuite/ld-elf/dt-relr.exp         | 44 +++++++++++++
> >> > 6 files changed, 155 insertions(+), 1 deletion(-)
> >> > create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1.c
> >> > create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1a.rd
> >> > create mode 100644 ld/testsuite/ld-elf/dt-relr-glibc-1b.rd
> >> > create mode 100644 ld/testsuite/ld-elf/dt-relr.exp
> >> >
> >> >diff --git a/bfd/elflink.c b/bfd/elflink.c
> >> >index 31b13f5df7a..05ac1cb7a63 100644
> >> >--- a/bfd/elflink.c
> >> >+++ b/bfd/elflink.c
> >> >@@ -2213,6 +2213,85 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
> >> >   return true;
> >> > }
> >> >
> >> >+/* Return true if GLIBC_ABI_DT_RELR is added to the list of version
> >> >+   dependencies successfully.  GLIBC_ABI_DT_RELR will be put into the
> >> >+   .gnu.version_r section.  */
> >> >+
> >> >+static bool
> >> >+elf_link_add_dt_relr_dependency (struct elf_find_verdep_info *rinfo)
> >> >+{
> >> >+  bfd *glibc_bfd = NULL;
> >> >+  Elf_Internal_Verneed *t;
> >> >+  Elf_Internal_Vernaux *a;
> >> >+  size_t amt;
> >> >+  const char *relr = "GLIBC_ABI_DT_RELR";
> >> >+
> >> >+  /* See if we already know about GLIBC_PRIVATE_DT_RELR.  */
> >> >+  for (t = elf_tdata (rinfo->info->output_bfd)->verref;
> >> >+       t != NULL;
> >> >+       t = t->vn_nextref)
> >> >+    {
> >> >+      const char *soname = bfd_elf_get_dt_soname (t->vn_bfd);
> >> >+      /* Skip the shared library if it isn't libc.so.  */
> >> >+      if (!soname || !startswith (soname, "libc.so."))
> >> >+      continue;
> >>
> >> Having the dependency on ld.so is better.
> >> (The linker knows the --dynamic-linker value.)
> >> libc.so does not need to know whether DT_RELR is used.
> >>
> >> It's also easier on glibc side.
> >> Defining  __glibc_abi_dt_relr@@GLIBC_ABI_DT_RELR in elf/Versions is
> >> simpler than defining it in libc.so and updating every libc.abilist.
> >
> >I chose libc.so instead of ld.so since shared libraries may
> >not be linked against ld.so.  The glibc change can be simple:
> >
> >https://patchwork.sourceware.org/project/glibc/patch/20211123223053.3334224-1-hjl.tools@gmail.com/
> >
> >Please replace GLIBC_ABI_VERSION_GEN2 with
> >GLIBC_ABI_DT_RELR.
> >
> >or like
> >
> >https://gitlab.com/x86-glibc/glibc/-/commit/3bc53baa5304855b5105dabd7726b23d454605fb
> >
> >I can go either way.
>
> OK... I picked the first way:
> https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/maskray/relr

Here it is:

https://gitlab.com/x86-glibc/glibc/-/commit/0cef25a4c61f39355224c13ae4f5c15f036659f7

--
H.J.

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2022-01-08 18:38 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-07 19:06 [PATCH 0/10] ld: Implement DT_RELR for x86 H.J. Lu
2022-01-07 19:06 ` [PATCH 01/10] ld: Extract _bfd_elf_link_iterate_on_relocs H.J. Lu
2022-01-07 19:06 ` [PATCH 02/10] elf: Add .relr.dyn to special_sections_r H.J. Lu
2022-01-07 19:06 ` [PATCH 03/10] elf: Extract _bfd_elf_process_reverse_copy H.J. Lu
2022-01-07 19:06 ` [PATCH 04/10] elf: Pass need_layout to _bfd_elf_map_sections_to_segments H.J. Lu
2022-01-07 19:06 ` [PATCH 05/10] ld: Initial DT_RELR support H.J. Lu
2022-01-08  2:10   ` Fangrui Song
2022-01-08  2:42     ` H.J. Lu
2022-01-08 18:32       ` H.J. Lu
2022-01-08  8:30   ` Fangrui Song
2022-01-08 13:19     ` H.J. Lu
2022-01-07 19:06 ` [PATCH 06/10] elf: Add size_relative_relocs and finish_relative_relocs H.J. Lu
2022-01-07 19:06 ` [PATCH 07/10] elf: Support DT_RELR in linker tests H.J. Lu
2022-01-08  2:42   ` Fangrui Song
2022-01-08 13:46     ` H.J. Lu
2022-01-07 19:06 ` [PATCH 08/10] x86: Add DT_RELR support H.J. Lu
2022-01-07 19:06 ` [PATCH 09/10] ld: Add simple DT_RELR tests H.J. Lu
2022-01-08  2:39   ` Fangrui Song
2022-01-08  2:44     ` H.J. Lu
2022-01-08  8:37   ` Fangrui Song
2022-01-08 18:33     ` H.J. Lu
2022-01-07 19:06 ` [PATCH 10/10] ld: Add glibc dependency for DT_RELR H.J. Lu
2022-01-08  4:43   ` Fangrui Song
2022-01-08  4:51     ` H.J. Lu
2022-01-08  8:19       ` Fangrui Song
2022-01-08 18:37         ` H.J. Lu
2022-01-07 23:45 ` [PATCH 0/10] ld: Implement DT_RELR for x86 Fangrui Song
2022-01-07 23:56   ` H.J. Lu
2022-01-08  1:31     ` Fangrui Song
2022-01-08  1:55       ` H.J. Lu
2022-01-08 18:30         ` 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).