This is the mail archive of the binutils-cvs@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]

[binutils-gdb] x86-64: Improve GOTPCREL relocation conversion


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8b43e456886c5b3aaba1ef93195ed888b15de242

commit 8b43e456886c5b3aaba1ef93195ed888b15de242
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Tue Sep 5 11:24:01 2017 -0700

    x86-64: Improve GOTPCREL relocation conversion
    
    When GOTPCREL relocation conversion leads to relocation overflow, we
    may get a mysterious linker message, like
    
    relocation truncated to fit: R_X86_64_32S against symbol `foo'
    
    This patch changes the linker message to
    
    failed to convert GOTPCREL relocation; relink with --no-relax
    
    bfd/
    
    	* elf64-x86-64.c (elf_x86_64_convert_load_reloc): Remove the sec
    	argument.  Don't check relocation overflow.  Avoid relocation
    	overflow if --no-relax is used.  Set converted_reloc on symbol
    	if a GOTPCREL relocation is converted.
    	(elf_x86_64_relocate_section): Issue a fatal error and suggest
    	--no-relax if GOTPCREL relocation conversion leads to relocation
    	overflow.
    	* elfxx-x86.h (elf_x86_link_hash_entry): Add converted_reloc.
    
    ld/
    
    	* testsuite/ld-x86-64/pr19609-4e.d: Updated.
    	* testsuite/ld-x86-64/pr19609-6a.d: Likewise.

Diff:
---
 bfd/ChangeLog                       |  11 +++
 bfd/elf64-x86-64.c                  | 132 +++++++-----------------------------
 bfd/elfxx-x86.h                     |   5 ++
 ld/ChangeLog                        |   5 ++
 ld/testsuite/ld-x86-64/pr19609-4e.d |   4 +-
 ld/testsuite/ld-x86-64/pr19609-6a.d |   2 +-
 6 files changed, 49 insertions(+), 110 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 1957ca9..551891d 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,14 @@
+2017-09-05  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* elf64-x86-64.c (elf_x86_64_convert_load_reloc): Remove the sec
+	argument.  Don't check relocation overflow.  Avoid relocation
+	overflow if --no-relax is used.  Set converted_reloc on symbol
+	if a GOTPCREL relocation is converted.
+	(elf_x86_64_relocate_section): Issue a fatal error and suggest
+	--no-relax if GOTPCREL relocation conversion leads to relocation
+	overflow.
+	* elfxx-x86.h (elf_x86_link_hash_entry): Add converted_reloc.
+
 2017-09-05  Alexander Fedotov <alexander.fedotov@nxp.com>
 	    Edmar Wienskoski <edmar.wienskoski@nxp.com
 
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index fa295a5..ddbf133 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1438,7 +1438,7 @@ elf_x86_64_need_pic (struct bfd_link_info *info,
    instructions.  */
 
 static bfd_boolean
-elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
+elf_x86_64_convert_load_reloc (bfd *abfd,
 			       bfd_byte *contents,
 			       Elf_Internal_Rela *irel,
 			       struct elf_link_hash_entry *h,
@@ -1447,17 +1447,15 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
 {
   struct elf_x86_link_hash_table *htab;
   bfd_boolean is_pic;
-  bfd_boolean require_reloc_pc32;
+  bfd_boolean no_overflow;
   bfd_boolean relocx;
   bfd_boolean to_reloc_pc32;
   asection *tsec;
-  char symtype;
   bfd_signed_vma raddend;
   unsigned int opcode;
   unsigned int modrm;
   unsigned int r_type = ELF32_R_TYPE (irel->r_info);
   unsigned int r_symndx;
-  bfd_vma toff;
   bfd_vma roff = irel->r_offset;
 
   if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2))
@@ -1474,10 +1472,8 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
   relocx = (r_type == R_X86_64_GOTPCRELX
 	    || r_type == R_X86_64_REX_GOTPCRELX);
 
-  /* TRUE if we can convert only to R_X86_64_PC32.  Enable it for
-     --no-relax.  */
-  require_reloc_pc32
-    = link_info->disable_target_specific_optimizations > 1;
+  /* TRUE if --no-relax is used.  */
+  no_overflow = link_info->disable_target_specific_optimizations > 1;
 
   r_symndx = htab->r_sym (irel->r_info);
 
@@ -1496,12 +1492,12 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
   /* We convert only to R_X86_64_PC32:
      1. Branch.
      2. R_X86_64_GOTPCREL since we can't modify REX byte.
-     3. require_reloc_pc32 is true.
+     3. no_overflow is true.
      4. PIC.
      */
   to_reloc_pc32 = (opcode == 0xff
 		   || !relocx
-		   || require_reloc_pc32
+		   || no_overflow
 		   || is_pic);
 
   /* Get the symbol referred to by the reloc.  */
@@ -1514,8 +1510,6 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
       if (isym->st_shndx == SHN_UNDEF)
 	return TRUE;
 
-      symtype = ELF_ST_TYPE (isym->st_info);
-
       if (isym->st_shndx == SHN_ABS)
 	tsec = bfd_abs_section_ptr;
       else if (isym->st_shndx == SHN_COMMON)
@@ -1524,8 +1518,6 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
 	tsec = &_bfd_elf_large_com_section;
       else
 	tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
-
-      toff = isym->st_value;
     }
   else
     {
@@ -1545,7 +1537,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
 	    {
 	      /* Skip for branch instructions since R_X86_64_PC32
 		 may overflow.  */
-	      if (require_reloc_pc32)
+	      if (no_overflow)
 		return TRUE;
 	    }
 	  else if (relocx)
@@ -1586,13 +1578,11 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
 			  && h->root.u.def.section == bfd_und_section_ptr))))
 	    {
 	      /* Skip since R_X86_64_32/R_X86_64_32S may overflow.  */
-	      if (require_reloc_pc32)
+	      if (no_overflow)
 		return TRUE;
 	      goto convert;
 	    }
 	  tsec = h->root.u.def.section;
-	  toff = h->root.u.def.value;
-	  symtype = h->type;
 	}
       else
 	return TRUE;
@@ -1603,92 +1593,12 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
       && (elf_section_flags (tsec) & SHF_X86_64_LARGE) != 0)
     return TRUE;
 
-  /* We can only estimate relocation overflow for R_X86_64_PC32.  */
-  if (!to_reloc_pc32)
-    goto convert;
-
-  if (tsec->sec_info_type == SEC_INFO_TYPE_MERGE)
-    {
-      /* At this stage in linking, no SEC_MERGE symbol has been
-	 adjusted, so all references to such symbols need to be
-	 passed through _bfd_merged_section_offset.  (Later, in
-	 relocate_section, all SEC_MERGE symbols *except* for
-	 section symbols have been adjusted.)
-
-	 gas may reduce relocations against symbols in SEC_MERGE
-	 sections to a relocation against the section symbol when
-	 the original addend was zero.  When the reloc is against
-	 a section symbol we should include the addend in the
-	 offset passed to _bfd_merged_section_offset, since the
-	 location of interest is the original symbol.  On the
-	 other hand, an access to "sym+addend" where "sym" is not
-	 a section symbol should not include the addend;  Such an
-	 access is presumed to be an offset from "sym";  The
-	 location of interest is just "sym".  */
-      if (symtype == STT_SECTION)
-	toff += raddend;
-
-      toff = _bfd_merged_section_offset (abfd, &tsec,
-					 elf_section_data (tsec)->sec_info,
-					 toff);
-
-      if (symtype != STT_SECTION)
-	toff += raddend;
-    }
-  else
-    toff += raddend;
-
-  /* Don't convert if R_X86_64_PC32 relocation overflows.  */
-  if (tsec->output_section == sec->output_section)
-    {
-      if ((toff - roff + 0x80000000) > 0xffffffff)
-	return TRUE;
-    }
-  else
-    {
-      bfd_signed_vma distance;
-
-      /* At this point, we don't know the load addresses of TSEC
-	 section nor SEC section.  We estimate the distrance between
-	 SEC and TSEC.  We store the estimated distances in the
-	 compressed_size field of the output section, which is only
-	 used to decompress the compressed input section.  */
-      if (sec->output_section->compressed_size == 0)
-	{
-	  asection *asect;
-	  bfd_size_type size = 0;
-	  for (asect = link_info->output_bfd->sections;
-	       asect != NULL;
-	       asect = asect->next)
-	    /* Skip debug sections since compressed_size is used to
-	       compress debug sections.  */
-	    if ((asect->flags & SEC_DEBUGGING) == 0)
-	      {
-		asection *i;
-		for (i = asect->map_head.s;
-		     i != NULL;
-		     i = i->map_head.s)
-		  {
-		    size = align_power (size, i->alignment_power);
-		    size += i->size;
-		  }
-		asect->compressed_size = size;
-	      }
-	}
-
-      /* Don't convert GOTPCREL relocations if TSEC isn't placed
-	 after SEC.  */
-      distance = (tsec->output_section->compressed_size
-		  - sec->output_section->compressed_size);
-      if (distance < 0)
-	return TRUE;
+  /* Skip since R_X86_64_PC32/R_X86_64_32/R_X86_64_32S may overflow.  */
+  if (no_overflow)
+    return TRUE;
 
-      /* Take PT_GNU_RELRO segment into account by adding
-	 maxpagesize.  */
-      if ((toff + distance + get_elf_backend_data (abfd)->maxpagesize
-	   - roff + 0x80000000) > 0xffffffff)
-	return TRUE;
-    }
+  if (h != NULL)
+    ((struct elf_x86_link_hash_entry *) h)->converted_reloc = 1;
 
 convert:
   if (opcode == 0xff)
@@ -2467,7 +2377,7 @@ _bfd_x86_64_elf_convert_load (bfd *abfd, asection *sec,
 	continue;
 
       converted = FALSE;
-      if (!elf_x86_64_convert_load_reloc (abfd, sec, contents, irel, h,
+      if (!elf_x86_64_convert_load_reloc (abfd, contents, irel, h,
 					  &converted, link_info))
 	goto error_return;
 
@@ -4099,9 +4009,17 @@ check_relocation_error:
 	    }
 
 	  if (r == bfd_reloc_overflow)
-	    (*info->callbacks->reloc_overflow)
-	      (info, (h ? &h->root : NULL), name, howto->name,
-	       (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
+	    {
+	      if (eh != NULL && eh->converted_reloc)
+		{
+		  info->callbacks->einfo
+		    (_("%F%P: failed to convert GOTPCREL relocation; relink with --no-relax\n"));
+		  return FALSE;
+		}
+	      (*info->callbacks->reloc_overflow)
+		(info, (h ? &h->root : NULL), name, howto->name,
+		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
+	    }
 	  else
 	    {
 	      _bfd_error_handler
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index 9c0dcbbe..775e025 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -110,6 +110,11 @@ struct elf_x86_link_hash_entry
      is only used by x86-64.  */
   unsigned int needs_copy : 1;
 
+  /* TRUE if a symbol with GOTPCREL relocations which have been converted
+     to R_X86_64_PC32, R_X86_64_32 or R_X86_64_32S.  This is only used by
+     x86-64 for now.  */
+  unsigned int converted_reloc : 1;
+
   /* Reference count of C/C++ function pointer relocations in read-write
      section which can be resolved at run-time.  */
   bfd_signed_vma func_pointer_refcount;
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 1fbec40..983c471 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,8 @@
+2017-09-05  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* testsuite/ld-x86-64/pr19609-4e.d: Updated.
+	* testsuite/ld-x86-64/pr19609-6a.d: Likewise.
+
 2017-09-03  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR ld/22071
diff --git a/ld/testsuite/ld-x86-64/pr19609-4e.d b/ld/testsuite/ld-x86-64/pr19609-4e.d
index 527fe5d..f263494 100644
--- a/ld/testsuite/ld-x86-64/pr19609-4e.d
+++ b/ld/testsuite/ld-x86-64/pr19609-4e.d
@@ -9,5 +9,5 @@
 Disassembly of section .text:
 
 0+70000000 <_start>:
-[ 	]*[a-f0-9]+:	48 8d 05 f9 ff ff 2f 	lea    0x2ffffff9\(%rip\),%rax        # a0000000 <foo>
-[ 	]*[a-f0-9]+:	4c 8d 1d f2 ff ff 2f 	lea    0x2ffffff2\(%rip\),%r11        # a0000000 <foo>
+[ 	]*[a-f0-9]+:	48 8b 05 ([0-9a-f]{2} ){4} *	mov    [-]?0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <.got>
+[ 	]*[a-f0-9]+:	4c 8b 1d ([0-9a-f]{2} ){4} *	mov    [-]?0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <.got>
diff --git a/ld/testsuite/ld-x86-64/pr19609-6a.d b/ld/testsuite/ld-x86-64/pr19609-6a.d
index 4802ffe..3c011d9 100644
--- a/ld/testsuite/ld-x86-64/pr19609-6a.d
+++ b/ld/testsuite/ld-x86-64/pr19609-6a.d
@@ -1,4 +1,4 @@
 #source: pr19609-6.s
 #as: --64 -mrelax-relocations=yes
 #ld: -melf_x86_64 --defsym foobar=0x80000000
-#error: .*relocation truncated to fit: R_X86_64_32S .*
+#error: failed to convert GOTPCREL relocation; relink with --no-relax


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