public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* PATCH:
@ 2010-08-25 16:58 H.J. Lu
  0 siblings, 0 replies; 8+ messages in thread
From: H.J. Lu @ 2010-08-25 16:58 UTC (permalink / raw)
  To: binutils; +Cc: Alan Modra

Hi,

I checked in this patch to move gas/ld NEWS from binutils to gas/ld.


H.J.
---
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 9f898a3..351fe47 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,7 +1,3 @@
-2010-08-25  Alan Modra  <amodra@gmail.com>
-
-	* NEWS: Mention ampersand in macro change.
-
 2010-08-23  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* elfedit.c (input_elf_osabi): New.
@@ -24,10 +20,6 @@
 	* readelf.c (display_mips_gnu_attribute): Replace GCC options
 	with a textual description of a MIPS32r2 64-bit FPU.
 
-2010-08-19  Alan Modra  <amodra@gmail.com>
-
-	* NEWS: Mention change in linker script expression evaluation.
-
 2010-08-13  Dan Rosenberg  <dan.j.rosenberg@gmail.com>
 
 	PR binutils/11889
diff --git a/binutils/NEWS b/binutils/NEWS
index e8e6d5c..92f894d 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -1,10 +1,5 @@
 -*- text -*-
 
-* Linker script expression evaluation is somewhat more sane.  This may
-  break scripts that depend on quirks of the old expression evaluation.
-
-* Gas no longer requires doubling of ampersands in macros.
-
 * Add support for the TMS320C6000 (TI C6X) processor family.
 
 * Readelf can now display ARM unwind tables (.ARM.exidx / .ARM.extab) using
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 0d5a24b..abec391 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,7 @@
+2010-08-25  Alan Modra  <amodra@gmail.com>
+
+	* NEWS: Mention ampersand in macro change.
+
 2010-08-25  Gunther Nikl  <gnikl@users.sourceforge.net>
 
 	* configure.tgt (m68k-*-aout): Change to bfd_gas=yes.
diff --git a/gas/NEWS b/gas/NEWS
index c7280bb..f762413 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,7 @@
 -*- text -*-
 
+* Gas no longer requires doubling of ampersands in macros.
+
 * Add support for the TMS320C6000 (TI C6X) processor family.
 
 * GAS now understands an extended syntax in the .section directive flags
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 55fd8e3..4038fd3 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -23,6 +23,10 @@
 
 2010-08-19  Alan Modra  <amodra@gmail.com>
 
+	* NEWS: Mention change in linker script expression evaluation.
+
+2010-08-19  Alan Modra  <amodra@gmail.com>
+
 	* ld.texinfo (Expression Section): Detail expression evaluation.
 	(Builtin Functions <ADDR>): Correct.
 	(Builtin Functions <LOADADDR>): Don't mention LOADADDR normally
diff --git a/ld/NEWS b/ld/NEWS
index b3fcb2a..9e7ad31 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Linker script expression evaluation is somewhat more sane.  This may
+  break scripts that depend on quirks of the old expression evaluation.
+
 * Turn off underscoring for x86_64 PE+-COFF targets.  For old behavior the
   option --enable-leading-mingw64-underscores can be used on configure of
   bfd.

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

* PATCH:
@ 2009-06-06 11:46 H.J. Lu
  0 siblings, 0 replies; 8+ messages in thread
From: H.J. Lu @ 2009-06-06 11:46 UTC (permalink / raw)
  To: binutils; +Cc: GNU C Library

We need dynamic relocation for STT_GNU_IFUNC symbol only when there is a
non-GOT reference in a shared object.

For STT_GNU_IFUNC symbol, .got.plt has the real function addres and
.got has the PLT entry adddress.  We will load the GOT entry with the
PLT entry if it used.  For branch, it uses .got.plt.  For symbol value,

1. Use .got.plt in a shared object if it is forced local or not dynamic.
2. Use .got.plt in a non-shared object if pointer equality isn't needed.
3. Use .got.plt if .got isn't used.
4. Otherwise use .got so that the single copy will be used among different
objects at run-time.

We only need to relocate .got entry in shared object.

I am checking in this patch to fix it.

H.J.
----
2009-06-06  H.J. Lu  <hongjiu.lu@intel.com>

	* elf32-i386.c (elf_i386_check_relocs): Make room for dynamic
	relocation for R_386_32 against STT_GNU_IFUNC symbol when
	building shared object.  Check info->executable instead of
	!info->shared when setting non_got_ref.
	(elf_i386_allocate_dynrelocs): Allocate dynamic relocation
	for non-GOT reference of STT_GNU_IFUNC symbol in shared
	object. Allocate GOT relocation agsinst STT_GNU_IFUNC
	symbol if needed.
	(elf_i386_relocate_section): Output dynamic relocation for
	R_386_32 against STT_GNU_IFUNC symbol to get the real
	function address when building shared object.
	(elf_i386_finish_dynamic_symbol): Output R_386_GLOB_DAT
	relocation for STT_GNU_IFUNC symbol in shared object.

	* elf64-x86-64.c (elf64_x86_64_check_relocs): Make room for
	dynamic relocation for R_X86_64_64 against STT_GNU_IFUNC
	symbol when building shared object.  Check info->executable
	instead of !info->shared when setting non_got_ref.
	(elf64_x86_64_allocate_dynrelocs): Allocate dynamic relocation
	for non-GOT reference of STT_GNU_IFUNC symbol in shared
	library. Allocate GOT relocation agsinst STT_GNU_IFUNC symbol
	if needed.
	(elf64_x86_64_relocate_section): Output dynamic relocation
	for R_X86_64_64 against STT_GNU_IFUNC symbol to get the real
	function address when building shared object.
	(elf64_x86_64_finish_dynamic_symbol): Output R_X86_64_GLOB_DAT
	relocation for STT_GNU_IFUNC symbol in shared object.

Index: elf32-i386.c
===================================================================
--- elf32-i386.c	(revision 6072)
+++ elf32-i386.c	(working copy)
@@ -1325,10 +1325,48 @@ elf_i386_check_relocs (bfd *abfd,
 		   return FALSE;
 
 		case R_386_32:
+		  h->non_got_ref = 1;
+		  h->pointer_equality_needed = 1;
+		  if (info->shared)
+		    {
+		      struct elf_i386_dyn_relocs *p;
+		      struct elf_i386_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)
+			{
+			  if (htab->elf.dynobj == NULL)
+			    htab->elf.dynobj = abfd;
+
+			  sreloc = _bfd_elf_make_dynamic_reloc_section
+			    (sec, htab->elf.dynobj, 2, abfd, FALSE);
+
+			  if (sreloc == NULL)
+			    return FALSE;
+			}
+
+		      head = &((struct elf_i386_link_hash_entry *) h)->dyn_relocs;
+		      p = *head;
+		      if (p == NULL || p->sec != sec)
+			{
+			  bfd_size_type amt = sizeof *p;
+			  p = bfd_alloc (htab->elf.dynobj, amt);
+			  if (p == NULL)
+			    return FALSE;
+			  p->next = *head;
+			  *head = p;
+			  p->sec = sec;
+			  p->count = 0;
+			  p->pc_count = 0;
+			}
+		      p->count += 1;
+		    }
+		  break;
+
 		case R_386_PC32:
 		  h->non_got_ref = 1;
-		  if (r_type != R_386_PC32)
-		    h->pointer_equality_needed = 1;
 		  break;
 
 		case R_386_PLT32:
@@ -1501,7 +1539,7 @@ elf_i386_check_relocs (bfd *abfd,
 
 	case R_386_32:
 	case R_386_PC32:
-	  if (h != NULL && !info->shared)
+	  if (h != NULL && info->executable)
 	    {
 	      /* If this reloc is in a read-only section, we might
 		 need a copy reloc.  We can't check reliably at this
@@ -1957,7 +1995,7 @@ elf_i386_allocate_dynrelocs (struct elf_
 
       /* When building a static executable, use .iplt, .igot.plt and
 	 .rel.iplt sections for STT_GNU_IFUNC symbols.  */
-      if (htab->splt != 0)
+      if (htab->splt != NULL)
 	{
 	  plt = htab->splt;
 	  gotplt = htab->sgotplt;
@@ -1992,34 +2030,50 @@ elf_i386_allocate_dynrelocs (struct elf_
       relplt->size += sizeof (Elf32_External_Rel);
       relplt->reloc_count++;
 
-      /* No need for dynamic relocation for local STT_GNU_IFUNC symbol.
-	 Discard space for relocations against it.  */
-      if (h->dynindx == -1 || h->forced_local)
+      /* We need dynamic relocation for STT_GNU_IFUNC symbol only
+	 when there is a non-GOT reference in a shared object.  */
+      if (!info->shared
+	  || !h->non_got_ref)
 	eh->dyn_relocs = NULL;
 
-      /* STT_GNU_IFUNC symbol uses .got.plt, not .got.  But for
-	 shared library, we must go through GOT and we can't
-	 use R_386_IRELATIVE unless it is forced local.   */
-      if (info->executable
-	  || info->symbolic
-	  || h->forced_local)
-	{
-	  if (h->pointer_equality_needed
-	      && htab->sgot != NULL)
-	    {
-	      /* We can't use .got.plt, which contains the real
-		 function addres, since we need pointer equality.
-		 We will load the GOT entry with the PLT entry
-		 in elf_i386_finish_dynamic_symbol and don't
-		 need GOT relocation.  */
-	      h->got.offset = htab->sgot->size;
-	      htab->sgot->size += 4;
-	      eh->tlsdesc_got = (bfd_vma) -1;
-	      goto skip_relgot;
-	    }
-	  else
-	    h->got.refcount = 0;
+      /* Finally, allocate space.  */
+      for (p = eh->dyn_relocs; p != NULL; p = p->next)
+	{
+	  asection * sreloc = elf_section_data (p->sec)->sreloc;
+	  sreloc->size += p->count * sizeof (Elf32_External_Rel);
+	}
+
+      /* For STT_GNU_IFUNC symbol, .got.plt has the real function
+	 addres and .got has the PLT entry adddress.  We will load
+	 the GOT entry with the PLT entry in finish_dynamic_symbol if
+	 it is used.  For branch, it uses .got.plt.  For symbol value,
+	 1. Use .got.plt in a shared object if it is forced local or
+	 not dynamic.
+	 2. Use .got.plt in a non-shared object if pointer equality 
+	 isn't needed.
+	 3. Use .got.plt if .got isn't used.
+	 4. Otherwise use .got so that it can be shared among different
+	 objects at run-time.
+	 We only need to relocate .got entry in shared object.  */
+      if ((info->shared
+	   && (h->dynindx == -1
+	       || h->forced_local))
+	  || (!info->shared
+	      && !h->pointer_equality_needed)
+	  || htab->sgot == NULL)
+	{
+	  /* Use .got.plt.  */
+	  h->got.offset = (bfd_vma) -1;
 	}
+      else
+	{
+	  h->got.offset = htab->sgot->size;
+	  htab->sgot->size += 4;
+	  if (info->shared)
+	    htab->srelgot->size += sizeof (Elf32_External_Rel);
+	}
+
+      return TRUE;
     }
   else if (htab->elf.dynamic_sections_created
 	   && h->plt.refcount > 0)
@@ -2166,7 +2220,6 @@ elf_i386_allocate_dynrelocs (struct elf_
   else
     h->got.offset = (bfd_vma) -1;
 
-skip_relgot:
   if (eh->dyn_relocs == NULL)
     return TRUE;
 
@@ -2920,6 +2973,57 @@ elf_i386_relocate_section (bfd *output_b
 	      return FALSE;
 
 	    case R_386_32:
+	      /* Generate dynamic relcoation only when there is a
+		 non-GOF reference in a shared object.  */
+	      if (info->shared && h->non_got_ref)
+		{
+		  Elf_Internal_Rela outrel;
+		  bfd_byte *loc;
+		  asection *sreloc;
+		  bfd_vma offset;
+
+		  /* Need a dynamic relocation get the the real
+		     function adddress.  */
+		  offset = _bfd_elf_section_offset (output_bfd,
+						    info,
+						    input_section,
+						    rel->r_offset);
+		  if (offset == (bfd_vma) -1
+		      || offset == (bfd_vma) -2)
+		    abort ();
+
+		  outrel.r_offset = (input_section->output_section->vma
+				     + input_section->output_offset
+				     + offset);
+
+		  if (h->dynindx == -1
+		      || h->forced_local)
+		    {
+		      /* This symbol is resolved locally.  */
+		      outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
+		      bfd_put_32 (output_bfd,
+				  (h->root.u.def.value 
+				   + h->root.u.def.section->output_section->vma
+				   + h->root.u.def.section->output_offset),
+				  contents + offset);
+		    }
+		  else
+		    outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
+
+		  sreloc = elf_section_data (input_section)->sreloc;
+		  loc = sreloc->contents;
+		  loc += (sreloc->reloc_count++
+			  * sizeof (Elf32_External_Rel));
+		  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
+
+		  /* If this reloc is against an external symbol, we
+		     do not want to fiddle with the addend.  Otherwise,
+		     we need to include the symbol value so that it
+		     becomes an addend for the dynamic reloc.  For an
+		     internal symbol, we have updated addend.  */
+		  continue;
+		}
+
 	    case R_386_PC32:
 	    case R_386_PLT32:
 	      goto do_relocation;
@@ -3950,7 +4054,7 @@ elf_i386_finish_dynamic_symbol (bfd *out
 
       /* When building a static executable, use .iplt, .igot.plt and
 	 .rel.iplt sections for STT_GNU_IFUNC symbols.  */
-      if (htab->splt != 0)
+      if (htab->splt != NULL)
 	{
 	  plt = htab->splt;
 	  gotplt = htab->sgotplt;
@@ -4132,25 +4236,29 @@ elf_i386_finish_dynamic_symbol (bfd *out
 	 of a version file, we just want to emit a RELATIVE reloc.
 	 The entry in the global offset table will already have been
 	 initialized in the relocate_section function.  */
-      if ((info->executable
-	   || info->symbolic
-	   || h->forced_local)
-	  && h->def_regular
-	  && h->pointer_equality_needed
+      if (h->def_regular
 	  && h->type == STT_GNU_IFUNC)
 	{
-	  /* The STT_GNU_IFUNC symbol is locally defined.  But we can't
-	     use .got.plt, which contains the real function addres,
-	     since we need pointer equality.  We load the GOT entry
-	     with the PLT entry without relocation.  */
-	  asection *plt = htab->splt ? htab->splt : htab->iplt;
-	  if (htab->sgot == NULL
-	      || h->plt.offset == (bfd_vma) -1)
-	    abort ();
-	  bfd_put_32 (output_bfd, (plt->output_section->vma
-				   + plt->output_offset + h->plt.offset),
-		      htab->sgot->contents + h->got.offset);
-	  return TRUE;
+	  if (info->shared)
+	    {
+	      /* Generate R_386_GLOB_DAT.  */
+	      goto do_glob_dat;
+	    }
+	  else
+	    {
+	      if (!h->pointer_equality_needed)
+		abort ();
+
+	      /* For non-shared object, we can't use .got.plt, which
+		 contains the real function addres if we need pointer
+		 equality.  We load the GOT entry with the PLT entry.  */
+	      asection *plt = htab->splt ? htab->splt : htab->iplt;
+	      bfd_put_32 (output_bfd,
+			  (plt->output_section->vma
+			   + plt->output_offset + h->plt.offset),
+			  htab->sgot->contents + h->got.offset);
+	      return TRUE;
+	    }
 	}
       else if (info->shared
 	       && SYMBOL_REFERENCES_LOCAL (info, h))
@@ -4161,6 +4269,7 @@ elf_i386_finish_dynamic_symbol (bfd *out
       else
 	{
 	  BFD_ASSERT((h->got.offset & 1) == 0);
+do_glob_dat:
 	  bfd_put_32 (output_bfd, (bfd_vma) 0,
 		      htab->sgot->contents + h->got.offset);
 	  rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT);
Index: elf64-x86-64.c
===================================================================
--- elf64-x86-64.c	(revision 6072)
+++ elf64-x86-64.c	(working copy)
@@ -1110,9 +1110,51 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		   bfd_set_error (bfd_error_bad_value);
 		   return FALSE;
 
+		case R_X86_64_64:
+		  h->non_got_ref = 1;
+		  h->pointer_equality_needed = 1;
+		  if (info->shared)
+		    {
+		      struct elf64_x86_64_dyn_relocs *p;
+		      struct elf64_x86_64_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)
+			{
+			  if (htab->elf.dynobj == NULL)
+			    htab->elf.dynobj = abfd;
+
+			  sreloc = _bfd_elf_make_dynamic_reloc_section
+			    (sec, htab->elf.dynobj, 3, abfd, TRUE);
+
+			  if (sreloc == NULL)
+			    return FALSE;
+			}
+		      
+		      head = &((struct elf64_x86_64_link_hash_entry *) h)->dyn_relocs;
+		      p = *head;
+		      if (p == NULL || p->sec != sec)
+			{
+			  bfd_size_type amt = sizeof *p;
+
+			  p = ((struct elf64_x86_64_dyn_relocs *)
+			       bfd_alloc (htab->elf.dynobj, amt));
+			  if (p == NULL)
+			    return FALSE;
+			  p->next = *head;
+			  *head = p;
+			  p->sec = sec;
+			  p->count = 0;
+			  p->pc_count = 0;
+			}
+		      p->count += 1;
+		    }
+		  break;
+
 		case R_X86_64_32S:
 		case R_X86_64_32:
-		case R_X86_64_64:
 		case R_X86_64_PC32:
 		case R_X86_64_PC64:
 		  h->non_got_ref = 1;
@@ -1329,7 +1371,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	case R_X86_64_PC32:
 	case R_X86_64_PC64:
 	case R_X86_64_64:
-	  if (h != NULL && !info->shared)
+	  if (h != NULL && info->executable)
 	    {
 	      /* If this reloc is in a read-only section, we might
 		 need a copy reloc.  We can't check reliably at this
@@ -1795,7 +1837,7 @@ elf64_x86_64_allocate_dynrelocs (struct 
 
       /* When building a static executable, use .iplt, .igot.plt and
 	 .rela.iplt sections for STT_GNU_IFUNC symbols.  */
-      if (htab->splt != 0)
+      if (htab->splt != NULL)
 	{
 	  plt = htab->splt;
 	  gotplt = htab->sgotplt;
@@ -1830,34 +1872,50 @@ elf64_x86_64_allocate_dynrelocs (struct 
       relplt->size += sizeof (Elf64_External_Rela);
       relplt->reloc_count++;
 
-      /* No need for dynamic relocation for local STT_GNU_IFUNC symbol.
-	 Discard space for relocations against it.  */
-      if (h->dynindx == -1 || h->forced_local)
+      /* We need dynamic relocation for STT_GNU_IFUNC symbol only
+	 when there is a non-GOT reference in a shared object.  */
+      if (!info->shared
+	  || !h->non_got_ref)
 	eh->dyn_relocs = NULL;
 
-      /* STT_GNU_IFUNC symbol uses .got.plt, not .got.  But for
-	 shared library, we must go through GOT and we can't
-	 use R_X86_64_IRELATIVE unless it is forced local.   */
-      if (info->executable
-	  || info->symbolic
-	  || h->forced_local)
-	{
-	  if (h->pointer_equality_needed
-	      && htab->sgot != NULL)
-	    {
-	      /* We can't use .got.plt, which contains the real
-		 function addres, since we need pointer equality.
-		 We will load the GOT entry with the PLT entry
-		 in elf64_x86_64_finish_dynamic_symbol and don't
-		 need GOT relocation.  */
-	      h->got.offset = htab->sgot->size;
-	      htab->sgot->size += GOT_ENTRY_SIZE;
-	      eh->tlsdesc_got = (bfd_vma) -1;
-	      goto skip_relgot;
-	    }
-	  else
-	    h->got.refcount = 0;
+      /* Finally, allocate space.  */
+      for (p = eh->dyn_relocs; p != NULL; p = p->next)
+	{
+	  asection * sreloc = elf_section_data (p->sec)->sreloc;
+	  sreloc->size += p->count * sizeof (Elf64_External_Rela);
+	}
+
+      /* For STT_GNU_IFUNC symbol, .got.plt has the real function
+	 addres and .got has the PLT entry adddress.  We will load
+	 the GOT entry with the PLT entry in finish_dynamic_symbol if
+	 it is used.  For branch, it uses .got.plt.  For symbol value,
+	 1. Use .got.plt in a shared object if it is forced local or
+	 not dynamic.
+	 2. Use .got.plt in a non-shared object if pointer equality 
+	 isn't needed.
+	 3. Use .got.plt if .got isn't used.
+	 4. Otherwise use .got so that it can be shared among different
+	 objects at run-time.
+	 We only need to relocate .got entry in shared object.  */
+      if ((info->shared
+	   && (h->dynindx == -1
+	       || h->forced_local))
+	  || (!info->shared
+	      && !h->pointer_equality_needed)
+	  || htab->sgot == NULL)
+	{
+	  /* Use .got.plt.  */
+	  h->got.offset = (bfd_vma) -1;
 	}
+      else
+	{
+	  h->got.offset = htab->sgot->size;
+	  htab->sgot->size += GOT_ENTRY_SIZE;
+	  if (info->shared)
+	    htab->srelgot->size += sizeof (Elf64_External_Rela);
+	}
+
+      return TRUE;
     }
   else if (htab->elf.dynamic_sections_created
 	   && h->plt.refcount > 0)
@@ -1984,7 +2042,6 @@ elf64_x86_64_allocate_dynrelocs (struct 
   else
     h->got.offset = (bfd_vma) -1;
 
-skip_relgot:
   if (eh->dyn_relocs == NULL)
     return TRUE;
 
@@ -2621,11 +2678,73 @@ elf64_x86_64_relocate_section (bfd *outp
 	      return FALSE;
 
 	    case R_X86_64_32S:
-	      if (!info->executable)
+	      if (info->shared)
 		abort ();
+	      goto do_relocation;
+
+	    case R_X86_64_64: 
+	      if (rel->r_addend != 0)
+		{
+		  (*_bfd_error_handler)
+		    (_("%B: relocation %s against STT_GNU_IFUNC "
+		       "symbol `%s' has non-zero addend: %d"),
+		     input_bfd, x86_64_elf_howto_table[r_type].name,
+		     h->root.root.string, rel->r_addend);
+		  bfd_set_error (bfd_error_bad_value);
+		  return FALSE;
+		}
+
+	      /* Generate dynamic relcoation only when there is a
+		 non-GOF reference in a shared object.  */
+	      if (info->shared && h->non_got_ref)
+		{
+		  Elf_Internal_Rela outrel;
+		  bfd_byte *loc;
+		  asection *sreloc;
+
+		  /* Need a dynamic relocation get the the real
+		     function address. */
+		  outrel.r_offset = _bfd_elf_section_offset (output_bfd,
+							     info,
+							     input_section,
+							     rel->r_offset);
+		  if (outrel.r_offset == (bfd_vma) -1
+		      || outrel.r_offset == (bfd_vma) -2)
+		    abort ();
+
+		  outrel.r_offset += (input_section->output_section->vma
+				      + input_section->output_offset);
+
+		  if (h->dynindx == -1
+		      || h->forced_local)
+		    {
+		      /* This symbol is resolved locally.  */
+		      outrel.r_info = ELF64_R_INFO (0, R_X86_64_IRELATIVE);
+		      outrel.r_addend = (h->root.u.def.value
+					 + h->root.u.def.section->output_section->vma
+					 + h->root.u.def.section->output_offset);
+		    }
+		  else
+		    {
+		      outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
+		      outrel.r_addend = 0;
+		    }
+
+		  sreloc = elf_section_data (input_section)->sreloc;
+		  loc = sreloc->contents;
+		  loc += (sreloc->reloc_count++
+			  * sizeof (Elf64_External_Rela));
+		  bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+
+		  /* If this reloc is against an external symbol, we
+		     do not want to fiddle with the addend.  Otherwise,
+		     we need to include the symbol value so that it
+		     becomes an addend for the dynamic reloc.  For an
+		     internal symbol, we have updated addend.  */
+		  continue;
+		}
 
 	    case R_X86_64_32:
-	    case R_X86_64_64:
 	    case R_X86_64_PC32:
 	    case R_X86_64_PC64:
 	    case R_X86_64_PLT32:
@@ -3596,7 +3715,7 @@ elf64_x86_64_finish_dynamic_symbol (bfd 
 
       /* When building a static executable, use .iplt, .igot.plt and
 	 .rela.iplt sections for STT_GNU_IFUNC symbols.  */
-      if (htab->splt != 0)
+      if (htab->splt != NULL)
 	{
 	  plt = htab->splt;
 	  gotplt = htab->sgotplt;
@@ -3741,25 +3860,29 @@ elf64_x86_64_finish_dynamic_symbol (bfd 
 	 of a version file, we just want to emit a RELATIVE reloc.
 	 The entry in the global offset table will already have been
 	 initialized in the relocate_section function.  */
-      if ((info->executable
-	   || info->symbolic
-	   || h->forced_local)
-	  && h->def_regular
-	  && h->pointer_equality_needed
+      if (h->def_regular
 	  && h->type == STT_GNU_IFUNC)
 	{
-	  /* The STT_GNU_IFUNC symbol is locally defined.  But we can't
-	     use .got.plt, which contains the real function addres,
-	     since we need pointer equality.  We load the GOT entry
-	     with the PLT entry without relocation.  */
-	  asection *plt = htab->splt ? htab->splt : htab->iplt;
-	  if (htab->sgot == NULL
-	      || h->plt.offset == (bfd_vma) -1)
-	    abort ();
-	  bfd_put_64 (output_bfd, (plt->output_section->vma
-				   + plt->output_offset + h->plt.offset),
-		      htab->sgot->contents + h->got.offset);
-	  return TRUE;
+	  if (info->shared)
+	    {
+	      /* Generate R_X86_64_GLOB_DAT.  */
+	      goto do_glob_dat;
+	    }
+	  else
+	    {
+	      if (!h->pointer_equality_needed)
+		abort ();
+
+	      /* For non-shared object, we can't use .got.plt, which
+		 contains the real function addres if we need pointer
+		 equality.  We load the GOT entry with the PLT entry.  */
+	      asection *plt = htab->splt ? htab->splt : htab->iplt;
+	      bfd_put_64 (output_bfd, (plt->output_section->vma
+				       + plt->output_offset
+				       + h->plt.offset),
+			  htab->sgot->contents + h->got.offset);
+	      return TRUE;
+	    }
 	}
       else if (info->shared
 	       && SYMBOL_REFERENCES_LOCAL (info, h))
@@ -3775,6 +3898,7 @@ elf64_x86_64_finish_dynamic_symbol (bfd 
       else
 	{
 	  BFD_ASSERT((h->got.offset & 1) == 0);
+do_glob_dat:
 	  bfd_put_64 (output_bfd, (bfd_vma) 0,
 		      htab->sgot->contents + h->got.offset);
 	  rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_GLOB_DAT);

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

* PATCH:
  2005-12-18 23:42     ` H. J. Lu
@ 2005-12-18 23:59       ` H. J. Lu
  0 siblings, 0 replies; 8+ messages in thread
From: H. J. Lu @ 2005-12-18 23:59 UTC (permalink / raw)
  To: binutils; +Cc: amodra

On Sun, Dec 18, 2005 at 03:42:23PM -0800, H. J. Lu wrote:
> On Sat, Dec 17, 2005 at 12:46:44PM +1030, Alan Modra wrote:
> > On Fri, Dec 16, 2005 at 05:46:40PM -0800, H. J. Lu wrote:
> > > bad.o is generated by the new linker. Alan, can you take a look?
> > 
> > Sorry, not immediately.  I'm just about to leave for a week at the
> > beach with my family.
> > 
> 
> I opened a PR:
> 
> http://sourceware.org/bugzilla/show_bug.cgi?id=2065
> 
> and I am checking this testcase.
> 

The problem is introduced by

http://sourceware.org/ml/binutils/2005-11/msg00239.html

where the new prev field is never really set properly since the last
field used to set it points to the next field of the last element on
the list.

This hack seems to work for me. But I'd like to see the tail field in
lang_statement_list_type be removed if possible. Alan, can you take
a look after you come back?

Thanks.


H.J.
----
2005-12-18  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/2065
	* ldlang.h (lang_statement_list_type): Add last.
	* ldlang.c (file_chain): Set the last field.
	(lang_list_init): Likewise.
	(lang_insert_orphan): Likewise.
	(lang_statement_append): Likewise.
	(output_statement_newfunc): Set os.prev with last.

--- ld/ldlang.c.prev	2005-12-18 09:40:59.000000000 -0800
+++ ld/ldlang.c	2005-12-18 14:29:57.000000000 -0800
@@ -89,7 +89,7 @@ static void lang_do_version_exports_sect
 lang_output_section_statement_type *abs_output_section;
 lang_statement_list_type lang_output_section_statement;
 lang_statement_list_type *stat_ptr = &statement_list;
-lang_statement_list_type file_chain = { NULL, NULL };
+lang_statement_list_type file_chain = { NULL, NULL, NULL };
 struct bfd_sym_chain entry_symbol = { NULL, NULL };
 static const char *entry_symbol_default = "start";
 const char *entry_section = ".text";
@@ -742,6 +742,7 @@ void
 lang_list_init (lang_statement_list_type *list)
 {
   list->head = NULL;
+  list->last = NULL;
   list->tail = &list->head;
 }
 
@@ -912,8 +913,10 @@ output_statement_newfunc (struct bfd_has
 			 (lang_statement_union_type *) &ret->os,
 			 &ret->os.header.next);
 
-  ret->os.prev = &((*lang_output_section_statement.tail)
-		   ->output_section_statement);
+  if (lang_output_section_statement.last)
+    ret->os.prev
+      = &(lang_output_section_statement.last->output_section_statement);
+
   /* GCC's strict aliasing rules prevent us from just casting the
      address, so we store the pointer in a variable and cast that
      instead.  */
@@ -1531,7 +1534,10 @@ lang_insert_orphan (lang_input_statement
 	  /* Fix the global list pointer if we happened to tack our
 	     new list at the tail.  */
 	  if (*old->tail == add.head)
-	    old->tail = add.tail;
+	    {
+	      old->last = add.last;
+	      old->tail = add.tail;
+	    }
 
 	  /* Save the end of this list.  */
 	  place->stmt = add.tail;
@@ -5836,6 +5842,7 @@ lang_statement_append (lang_statement_li
 		       lang_statement_union_type **field)
 {
   *(list->tail) = element;
+  list->last = element;
   list->tail = field;
 }
 
--- ld/ldlang.h.prev	2005-12-18 09:40:59.000000000 -0800
+++ ld/ldlang.h	2005-12-18 14:12:14.000000000 -0800
@@ -44,6 +44,7 @@ struct _fill_type
 typedef struct statement_list
 {
   union lang_statement_union *head;
+  union lang_statement_union *last;
   union lang_statement_union **tail;
 } lang_statement_list_type;
 

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

* Re: PATCH:
  2004-08-11  1:02 ` PATCH: Alan Modra
@ 2004-08-11  2:13   ` Mark Mitchell
  0 siblings, 0 replies; 8+ messages in thread
From: Mark Mitchell @ 2004-08-11  2:13 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 344 bytes --]

Alan Modra wrote:

>On Tue, Aug 10, 2004 at 04:44:25PM -0700, Mark Mitchell wrote:
>  
>
>>	* expr.c (operand): Handle the "~", "-", and "!" operators applied
>>	to bignums.
>>    
>>
>
>OK.
>  
>
Here is the patch as checked in.  (I added a testsuite entry.)

Thanks,

-- 
Mark Mitchell
CodeSourcery, LLC
(916) 791-8304
mark@codesourcery.com


[-- Attachment #2: diffs --]
[-- Type: text/plain, Size: 2963 bytes --]

2004-08-10  Mark Mitchell  <mark@codesourcery.com>

	* expr.c (operand): Handle the "~", "-", and "!" operators applied
	to bignums.

2004-08-10  Mark Mitchell  <mark@codesourcery.com>

	* gas/arm/bignum1.s: New test.
	* gas/arm/arm.exp: Run it.

Index: expr.c
===================================================================
RCS file: /cvs/src/src/gas/expr.c,v
retrieving revision 1.51
diff -c -5 -p -r1.51 expr.c
*** expr.c	23 May 2004 04:35:11 -0000	1.51
--- expr.c	11 Aug 2004 02:10:05 -0000
*************** operand (expressionS *expressionP)
*** 1074,1083 ****
--- 1074,1112 ----
  	    if (generic_floating_point_number.sign == '+')
  	      generic_floating_point_number.sign = '-';
  	    else
  	      generic_floating_point_number.sign = 'N';
  	  }
+ 	else if (expressionP->X_op == O_big
+ 		 && expressionP->X_add_number > 0)
+ 	  {
+ 	    int i;
+ 
+ 	    if (c == '~' || c == '-')
+ 	      {
+ 		for (i = 0; i < expressionP->X_add_number; ++i)
+ 		  generic_bignum[i] = ~generic_bignum[i];
+ 		if (c == '-')
+ 		  for (i = 0; i < expressionP->X_add_number; ++i)
+ 		    {
+ 		      generic_bignum[i] += 1;
+ 		      if (generic_bignum[i])
+ 			break;
+ 		    }
+ 	      }
+ 	    else if (c == '!')
+ 	      {
+ 		int nonzero = 0;
+ 		for (i = 0; i < expressionP->X_add_number; ++i)
+ 		  {
+ 		    if (generic_bignum[i])
+ 		      nonzero = 1;
+ 		    generic_bignum[i] = 0;
+ 		  }
+ 		generic_bignum[0] = nonzero;
+ 	      }
+ 	  }
  	else if (expressionP->X_op != O_illegal
  		 && expressionP->X_op != O_absent)
  	  {
  	    expressionP->X_add_symbol = make_expr_symbol (expressionP);
  	    if (c == '-')
Index: testsuite/gas/arm/arm.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/arm.exp,v
retrieving revision 1.29
diff -c -5 -p -r1.29 arm.exp
*** testsuite/gas/arm/arm.exp	30 Apr 2004 10:51:13 -0000	1.29
--- testsuite/gas/arm/arm.exp	11 Aug 2004 02:10:05 -0000
*************** if {[istarget *arm*-*-*] || [istarget "x
*** 33,42 ****
--- 33,43 ----
      gas_test "arm7dm.s" "-mcpu=arm7dm" $stdoptlist "Arm 7DM instructions"
      gas_test "arch4t.s" "-march=armv4t" $stdoptlist "Arm architecture 4t instructions"
      gas_test "immed.s" "" $stdoptlist "immediate expressions"
      gas_test "float.s" "-mcpu=arm7tdmi -mfpu=fpa" $stdoptlist "Core floating point instructions"
      gas_test "offset.s" "" $stdoptlist "OFFSET_IMM regression"
+     gas_test "bignum1.s" "" $stdoptlist "bignums"
  
      run_dump_test "armv1"
      run_dump_test "arch5tej"
      run_dump_test "fpa-monadic"
      run_dump_test "fpa-dyadic"
Index: testsuite/gas/arm/bignum1.s
===================================================================
RCS file: testsuite/gas/arm/bignum1.s
diff -N testsuite/gas/arm/bignum1.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gas/arm/bignum1.s	11 Aug 2004 02:10:05 -0000
***************
*** 0 ****
--- 1 ----
+ 	.8byte	-9223372036854775808

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

* Re: PATCH:
  2004-08-10 23:44 PATCH: Mark Mitchell
  2004-08-11  0:04 ` PATCH: H. J. Lu
@ 2004-08-11  1:02 ` Alan Modra
  2004-08-11  2:13   ` PATCH: Mark Mitchell
  1 sibling, 1 reply; 8+ messages in thread
From: Alan Modra @ 2004-08-11  1:02 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: binutils

On Tue, Aug 10, 2004 at 04:44:25PM -0700, Mark Mitchell wrote:
> 	* expr.c (operand): Handle the "~", "-", and "!" operators applied
> 	to bignums.

OK.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

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

* Re: PATCH:
  2004-08-11  0:04 ` PATCH: H. J. Lu
@ 2004-08-11  0:44   ` Mark Mitchell
  0 siblings, 0 replies; 8+ messages in thread
From: Mark Mitchell @ 2004-08-11  0:44 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils

H. J. Lu wrote:

>On Tue, Aug 10, 2004 at 04:44:25PM -0700, Mark Mitchell wrote:
>  
>
>>In a 32-bit->64-bit cross compilation environment, GCC may emit 8-byte
>>integer literals as signed values.  However, GAS does not handle "-"
>>applied to a bignum, so the assembler will fail to assemble such
>>files.  This patch adds support for applying "~", "-", and "!" to
>>bignums in GAS.
>>
>>OK to apply?
>>
>>    
>>
>
>Can you add a testcase? I have been building ia64 binutils on ia32.
>  
>
Sure, I can add a testcase if the patch is approved.

It is basically just:

  .8byte - <big 64-bit number here>

-- 
Mark Mitchell
CodeSourcery, LLC
(916) 791-8304
mark@codesourcery.com

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

* Re: PATCH:
  2004-08-10 23:44 PATCH: Mark Mitchell
@ 2004-08-11  0:04 ` H. J. Lu
  2004-08-11  0:44   ` PATCH: Mark Mitchell
  2004-08-11  1:02 ` PATCH: Alan Modra
  1 sibling, 1 reply; 8+ messages in thread
From: H. J. Lu @ 2004-08-11  0:04 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: binutils

On Tue, Aug 10, 2004 at 04:44:25PM -0700, Mark Mitchell wrote:
> 
> In a 32-bit->64-bit cross compilation environment, GCC may emit 8-byte
> integer literals as signed values.  However, GAS does not handle "-"
> applied to a bignum, so the assembler will fail to assemble such
> files.  This patch adds support for applying "~", "-", and "!" to
> bignums in GAS.
> 
> OK to apply?
> 

Can you add a testcase? I have been building ia64 binutils on ia32.

Thanks.


H.J.

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

* PATCH:
@ 2004-08-10 23:44 Mark Mitchell
  2004-08-11  0:04 ` PATCH: H. J. Lu
  2004-08-11  1:02 ` PATCH: Alan Modra
  0 siblings, 2 replies; 8+ messages in thread
From: Mark Mitchell @ 2004-08-10 23:44 UTC (permalink / raw)
  To: binutils


In a 32-bit->64-bit cross compilation environment, GCC may emit 8-byte
integer literals as signed values.  However, GAS does not handle "-"
applied to a bignum, so the assembler will fail to assemble such
files.  This patch adds support for applying "~", "-", and "!" to
bignums in GAS.

OK to apply?

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2004-08-10  Mark Mitchell  <mark@codesourcery.com>

	* expr.c (operand): Handle the "~", "-", and "!" operators applied
	to bignums.

Index: gas/expr.c
===================================================================
RCS file: /cvs/src/src/gas/expr.c,v
retrieving revision 1.51
diff -c -5 -p -r1.51 expr.c
*** gas/expr.c	23 May 2004 04:35:11 -0000	1.51
--- gas/expr.c	10 Aug 2004 23:39:39 -0000
*************** operand (expressionS *expressionP)
*** 1074,1083 ****
--- 1074,1112 ----
  	    if (generic_floating_point_number.sign == '+')
  	      generic_floating_point_number.sign = '-';
  	    else
  	      generic_floating_point_number.sign = 'N';
  	  }
+ 	else if (expressionP->X_op == O_big
+ 		 && expressionP->X_add_number > 0)
+ 	  {
+ 	    int i;
+ 
+ 	    if (c == '~' || c == '-')
+ 	      {
+ 		for (i = 0; i < expressionP->X_add_number; ++i)
+ 		  generic_bignum[i] = ~generic_bignum[i];
+ 		if (c == '-')
+ 		  for (i = 0; i < expressionP->X_add_number; ++i)
+ 		    {
+ 		      generic_bignum[i] += 1;
+ 		      if (generic_bignum[i])
+ 			break;
+ 		    }
+ 	      }
+ 	    else if (c == '!')
+ 	      {
+ 		int nonzero = 0;
+ 		for (i = 0; i < expressionP->X_add_number; ++i)
+ 		  {
+ 		    if (generic_bignum[i])
+ 		      nonzero = 1;
+ 		    generic_bignum[i] = 0;
+ 		  }
+ 		generic_bignum[0] = nonzero;
+ 	      }
+ 	  }
  	else if (expressionP->X_op != O_illegal
  		 && expressionP->X_op != O_absent)
  	  {
  	    expressionP->X_add_symbol = make_expr_symbol (expressionP);
  	    if (c == '-')

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

end of thread, other threads:[~2010-08-25 16:05 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-25 16:58 PATCH: H.J. Lu
  -- strict thread matches above, loose matches on Subject: below --
2009-06-06 11:46 PATCH: H.J. Lu
2005-12-16 23:37 Possible problem with ia64 binutils H. J. Lu
2005-12-17  1:46 ` "ld -r" is broken H. J. Lu
2005-12-17  2:16   ` Alan Modra
2005-12-18 23:42     ` H. J. Lu
2005-12-18 23:59       ` PATCH: H. J. Lu
2004-08-10 23:44 PATCH: Mark Mitchell
2004-08-11  0:04 ` PATCH: H. J. Lu
2004-08-11  0:44   ` PATCH: Mark Mitchell
2004-08-11  1:02 ` PATCH: Alan Modra
2004-08-11  2:13   ` PATCH: Mark Mitchell

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).