This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] x86: Properly handle __ehdr_start


After _bfd_i386_elf_convert_load and _bfd_x86_64_elf_convert_load are
removed, elf_i386_convert_load_reloc and elf_x86_64_convert_load_reloc
see __ehdr_start as an undefined symbol when they are called from
check_relocs to convert GOT relocations against local symbols.  But
__ehdr_start will be defined as a hidden symbol by linker at the later
stage if it is referenced.  This patch marks __ehdr_start as a defined
local symbol at the start of check_relocs if it is referenced and not
defined.

bfd/

	PR ld/22115
	* elf32-i386.c (elf_i386_convert_load_reloc): Check linker_def.
	Don't use UNDEFINED_WEAK_RESOLVED_TO_ZERO.
	* elf64-x86-64.c (elf_x86_64_convert_load_reloc): Check
	linker_def.  Don't use UNDEFINED_WEAK_RESOLVED_TO_ZERO.
	* elfxx-x86.c (_bfd_x86_elf_link_check_relocs): Set local_ref
	and linker_def on __ehdr_start if it is referenced and not
	defined.
	(_bfd_x86_elf_link_symbol_references_local): Also set local_ref
	and return TRUE when building executable, if a symbol has
	non-GOT/non-PLT relocations in text section or there is no
	dynamic linker.
	* elfxx-x86.h (elf_x86_link_hash_entry): Add linker_def.

ld/

	PR ld/22115
	* ld-i386/i386.exp: Run PR ld/22115 tests,
	* ld/testsuite/ld-x86-64/x86-64.exp: Likewise.
	* testsuite/ld-i386/pr22115-1.s: New file.
	* testsuite/ld-i386/pr22115-1a.d: Likewise.
	* testsuite/ld-i386/pr22115-1b.d: Likewise.
	* testsuite/ld-x86-64/pr22115-1.s: Likewise.
	* testsuite/ld-x86-64/pr22115-1a-x32.d: Likewise.
	* testsuite/ld-x86-64/pr22115-1a.d: Likewise.
	* testsuite/ld-x86-64/pr22115-1b-x32.d: Likewise.
	* testsuite/ld-x86-64/pr22115-1b.d: Likewise.
---
 bfd/elf32-i386.c                        | 20 +++++++++++------
 bfd/elf64-x86-64.c                      | 16 ++++++++-----
 bfd/elfxx-x86.c                         | 40 ++++++++++++++++++++++++++-------
 bfd/elfxx-x86.h                         |  3 +++
 ld/testsuite/ld-i386/i386.exp           |  2 ++
 ld/testsuite/ld-i386/pr22115-1.s        |  7 ++++++
 ld/testsuite/ld-i386/pr22115-1a.d       | 13 +++++++++++
 ld/testsuite/ld-i386/pr22115-1b.d       |  6 +++++
 ld/testsuite/ld-x86-64/pr22115-1.s      |  7 ++++++
 ld/testsuite/ld-x86-64/pr22115-1a-x32.d | 13 +++++++++++
 ld/testsuite/ld-x86-64/pr22115-1a.d     | 13 +++++++++++
 ld/testsuite/ld-x86-64/pr22115-1b-x32.d |  6 +++++
 ld/testsuite/ld-x86-64/pr22115-1b.d     |  6 +++++
 ld/testsuite/ld-x86-64/x86-64.exp       |  4 ++++
 14 files changed, 136 insertions(+), 20 deletions(-)
 create mode 100644 ld/testsuite/ld-i386/pr22115-1.s
 create mode 100644 ld/testsuite/ld-i386/pr22115-1a.d
 create mode 100644 ld/testsuite/ld-i386/pr22115-1b.d
 create mode 100644 ld/testsuite/ld-x86-64/pr22115-1.s
 create mode 100644 ld/testsuite/ld-x86-64/pr22115-1a-x32.d
 create mode 100644 ld/testsuite/ld-x86-64/pr22115-1a.d
 create mode 100644 ld/testsuite/ld-x86-64/pr22115-1b-x32.d
 create mode 100644 ld/testsuite/ld-x86-64/pr22115-1b.d

diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index dcf07d95d8..0100662040 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1229,6 +1229,8 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
   unsigned int r_type;
   unsigned int r_symndx;
   bfd_vma roff = irel->r_offset;
+  bfd_boolean local_ref;
+  struct elf_x86_link_hash_entry *eh;
 
   if (roff < 2)
     return TRUE;
@@ -1276,6 +1278,8 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
      register.  */
   to_reloc_32 = !is_pic || baseless;
 
+  eh = elf_x86_hash_entry (h);
+
   /* Try to convert R_386_GOT32X.  Get the symbol referred to by the
      reloc.  */
   if (h == NULL)
@@ -1290,10 +1294,14 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
 	goto convert_load;
     }
 
+  /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P.  */
+  local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h);
+
   /* Undefined weak symbol is only bound locally in executable
      and its reference is resolved as 0.  */
-  if (UNDEFINED_WEAK_RESOLVED_TO_ZERO (link_info, I386_ELF_DATA, TRUE,
-				       elf_x86_hash_entry (h)))
+  if (h->root.type == bfd_link_hash_undefweak
+      && !eh->linker_def
+      && local_ref)
     {
       if (opcode == 0xff)
 	{
@@ -1316,16 +1324,13 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
       /* We have "call/jmp *foo@GOT[(%reg)]".  */
       if ((h->root.type == bfd_link_hash_defined
 	   || h->root.type == bfd_link_hash_defweak)
-	  && SYMBOL_REFERENCES_LOCAL_P (link_info, h))
+	  && local_ref)
 	{
 	  /* The function is locally defined.   */
 convert_branch:
 	  /* Convert R_386_GOT32X to R_386_PC32.  */
 	  if (modrm == 0x15 || (modrm & 0xf8) == 0x90)
 	    {
-	      struct elf_x86_link_hash_entry *eh
-		= (struct elf_x86_link_hash_entry *) h;
-
 	      /* Convert to "nop call foo".  ADDR_PREFIX_OPCODE
 		 is a nop prefix.  */
 	      modrm = 0xe8;
@@ -1381,10 +1386,11 @@ convert_branch:
 	 bfd_elf_record_link_assignment.  start_stop is set on
 	 __start_SECNAME/__stop_SECNAME which mark section SECNAME.  */
       if (h->start_stop
+	  || eh->linker_def
 	  || ((h->def_regular
 	       || h->root.type == bfd_link_hash_defined
 	       || h->root.type == bfd_link_hash_defweak)
-	      && SYMBOL_REFERENCES_LOCAL_P (link_info, h)))
+	      && local_ref))
 	{
 convert_load:
 	  if (opcode == 0x8b)
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index cab086db05..4faa78bf52 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1537,11 +1537,15 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
 	 GOTPCRELX relocations since we need to modify REX byte.
 	 It is OK convert mov with R_X86_64_GOTPCREL to
 	 R_X86_64_PC32.  */
+      bfd_boolean local_ref;
+      struct elf_x86_link_hash_entry *eh = elf_x86_hash_entry (h);
+
+      /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P.  */
+      local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h);
       if ((relocx || opcode == 0x8b)
-	  && UNDEFINED_WEAK_RESOLVED_TO_ZERO (link_info,
-					      X86_64_ELF_DATA,
-					      TRUE,
-					      elf_x86_hash_entry (h)))
+	  && (h->root.type == bfd_link_hash_undefweak
+	      && !eh->linker_def
+	      && local_ref))
 	{
 	  if (opcode == 0xff)
 	    {
@@ -1568,11 +1572,12 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
       /* Avoid optimizing GOTPCREL relocations againt _DYNAMIC since
 	 ld.so may use its link-time address.  */
       else if (h->start_stop
+	       || eh->linker_def
 	       || ((h->def_regular
 		    || h->root.type == bfd_link_hash_defined
 		    || h->root.type == bfd_link_hash_defweak)
 		   && h != htab->elf.hdynamic
-		   && SYMBOL_REFERENCES_LOCAL_P (link_info, h)))
+		   && local_ref))
 	{
 	  /* bfd_link_hash_new or bfd_link_hash_undefined is
 	     set by an assignment in a linker script in
@@ -1580,6 +1585,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
 	     on __start_SECNAME/__stop_SECNAME which mark section
 	     SECNAME.  */
 	  if (h->start_stop
+	      || eh->linker_def
 	      || (h->def_regular
 		  && (h->root.type == bfd_link_hash_new
 		      || h->root.type == bfd_link_hash_undefined
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 86e26f9852..828ce91314 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -845,12 +845,28 @@ _bfd_x86_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
       htab = elf_x86_hash_table (info, bed->target_id);
       if (htab)
 	{
-	  struct elf_link_hash_entry *h
-	    = elf_link_hash_lookup (elf_hash_table (info),
+	  struct elf_link_hash_entry *h;
+
+	  h = elf_link_hash_lookup (elf_hash_table (info),
 				    htab->tls_get_addr,
 				    FALSE, FALSE, FALSE);
 	  if (h != NULL)
-	    ((struct elf_x86_link_hash_entry *) h)->tls_get_addr = 1;
+	    elf_x86_hash_entry (h)->tls_get_addr = 1;
+
+	  /* "__ehdr_start" will be defined by linker as a hidden symbol
+	     later if it is referenced and not defined.  */
+	  h = elf_link_hash_lookup (elf_hash_table (info),
+				    "__ehdr_start",
+				    FALSE, FALSE, FALSE);
+	  if (h != NULL
+	      && (h->root.type == bfd_link_hash_new
+		  || h->root.type == bfd_link_hash_undefined
+		  || h->root.type == bfd_link_hash_undefweak
+		  || h->root.type == bfd_link_hash_common))
+	    {
+	      elf_x86_hash_entry (h)->local_ref = 2;
+	      elf_x86_hash_entry (h)->linker_def = 1;
+	    }
 	}
     }
 
@@ -1671,8 +1687,9 @@ bfd_boolean
 _bfd_x86_elf_link_symbol_references_local (struct bfd_link_info *info,
 					   struct elf_link_hash_entry *h)
 {
-  struct elf_x86_link_hash_entry *eh
-    = (struct elf_x86_link_hash_entry *) h;
+  struct elf_x86_link_hash_entry *eh = elf_x86_hash_entry (h);
+  struct elf_x86_link_hash_table *htab
+    = (struct elf_x86_link_hash_table *) info->hash;
 
   if (eh->local_ref > 1)
     return TRUE;
@@ -1681,11 +1698,18 @@ _bfd_x86_elf_link_symbol_references_local (struct bfd_link_info *info,
     return FALSE;
 
   /* Unversioned symbols defined in regular objects can be forced local
-     by linker version script.  A weak undefined symbol can fored local
-     if it has non-default visibility or "-z nodynamic-undefined-weak"
-     is used.  */
+     by linker version script.  A weak undefined symbol is forced local
+     if
+     1. It has non-default visibility.  Or
+     2. When building executable, it has non-GOT/non-PLT relocations
+	in text section or there is no dynamic linker.  Or
+     3. or "-z nodynamic-undefined-weak" is used.
+   */
   if (SYMBOL_REFERENCES_LOCAL (info, h)
       || ((ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+	   || (bfd_link_executable (info)
+	       && (htab->interp == NULL
+		   || eh->has_non_got_reloc))
 	   || info->dynamic_undefined_weak == 0)
 	  && h->root.type == bfd_link_hash_undefweak)
       || ((h->def_regular || ELF_COMMON_DEF_P (h))
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index ccc72dabf5..57f7862151 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -108,6 +108,9 @@ struct elf_x86_link_hash_entry
    */
   unsigned int local_ref : 2;
 
+  /* TRUE if symbol is defined by linker.  */
+  unsigned int linker_def : 1;
+
   /* Terue if symbol is referenced by R_386_GOTOFF relocation.  This is
      only used by i386.  */
   unsigned int gotoff_ref : 1;
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index bd1561024c..6f5be51e69 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -440,6 +440,8 @@ run_dump_test "pie1"
 run_dump_test "pie1-nacl"
 run_dump_test "pr21884"
 run_dump_test "pr21884-nacl"
+run_dump_test "pr22115-1a"
+run_dump_test "pr22115-1b"
 
 if { !([istarget "i?86-*-linux*"]
        || [istarget "i?86-*-gnu*"]
diff --git a/ld/testsuite/ld-i386/pr22115-1.s b/ld/testsuite/ld-i386/pr22115-1.s
new file mode 100644
index 0000000000..341eedec89
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr22115-1.s
@@ -0,0 +1,7 @@
+	.text
+	.globl	_start
+	.type	_start, @function
+_start:
+	movl	__ehdr_start@GOT(%eax), %eax
+	.size	_start, .-_start
+	.weak	__ehdr_start
diff --git a/ld/testsuite/ld-i386/pr22115-1a.d b/ld/testsuite/ld-i386/pr22115-1a.d
new file mode 100644
index 0000000000..4857952b65
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr22115-1a.d
@@ -0,0 +1,13 @@
+#source: pr22115-1.s
+#as: --32 -mrelax-relocations=yes
+#ld: -pie -z text -m elf_i386
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:	8d 80 ([0-9a-f]{2} ){4} *	lea    -?0x[a-f0-9]+\(%eax\),%eax
+#pass
diff --git a/ld/testsuite/ld-i386/pr22115-1b.d b/ld/testsuite/ld-i386/pr22115-1b.d
new file mode 100644
index 0000000000..bb05851678
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr22115-1b.d
@@ -0,0 +1,6 @@
+#source: pr22115-1.s
+#as: --32 -mrelax-relocations=yes
+#ld: -pie -z text -m elf_i386
+#readelf: -r
+
+There are no relocations in this file.
diff --git a/ld/testsuite/ld-x86-64/pr22115-1.s b/ld/testsuite/ld-x86-64/pr22115-1.s
new file mode 100644
index 0000000000..8c01e5065e
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22115-1.s
@@ -0,0 +1,7 @@
+	.text
+	.globl	_start
+	.type	_start, @function
+_start:
+	movq	__ehdr_start@GOTPCREL(%rip), %rax
+	.size	_start, .-_start
+	.weak	__ehdr_start
diff --git a/ld/testsuite/ld-x86-64/pr22115-1a-x32.d b/ld/testsuite/ld-x86-64/pr22115-1a-x32.d
new file mode 100644
index 0000000000..8232589211
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22115-1a-x32.d
@@ -0,0 +1,13 @@
+#source: pr22115-1.s
+#as: --x32 -mrelax-relocations=yes
+#ld: -pie -z text -m elf32_x86_64
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    -?0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <__ehdr_start>
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr22115-1a.d b/ld/testsuite/ld-x86-64/pr22115-1a.d
new file mode 100644
index 0000000000..43dc787a53
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22115-1a.d
@@ -0,0 +1,13 @@
+#source: pr22115-1.s
+#as: --64 -mrelax-relocations=yes
+#ld: -pie -z text -m elf_x86_64
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    -?0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <__ehdr_start>
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr22115-1b-x32.d b/ld/testsuite/ld-x86-64/pr22115-1b-x32.d
new file mode 100644
index 0000000000..949dc5f836
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22115-1b-x32.d
@@ -0,0 +1,6 @@
+#source: pr22115-1.s
+#as: --x32 -mrelax-relocations=yes
+#ld: -pie -z text -m elf32_x86_64
+#readelf: -r
+
+There are no relocations in this file.
diff --git a/ld/testsuite/ld-x86-64/pr22115-1b.d b/ld/testsuite/ld-x86-64/pr22115-1b.d
new file mode 100644
index 0000000000..f1aaf72663
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22115-1b.d
@@ -0,0 +1,6 @@
+#source: pr22115-1.s
+#as: --64 -mrelax-relocations=yes
+#ld: -pie -z text -m elf_x86_64
+#readelf: -r
+
+There are no relocations in this file.
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 46b3ec7979..59fbc8b117 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -369,6 +369,10 @@ run_dump_test "property-x86-shstk5-x32"
 run_dump_test "pr21884"
 run_dump_test "pr21884-nacl"
 run_dump_test "pr22071"
+run_dump_test "pr22115-1a"
+run_dump_test "pr22115-1a-x32"
+run_dump_test "pr22115-1b"
+run_dump_test "pr22115-1b-x32"
 
 if { ![istarget "x86_64-*-linux*"] && ![istarget "x86_64-*-nacl*"]} {
     return
-- 
2.13.5


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]