public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* How to avoid unnecessary R_IA64_FPTR64LSB in executable?
@ 2005-04-28  7:00 H. J. Lu
  2005-04-29  1:36 ` PATCH: Avoid unnecessary R_IA64_FPTR64LSB in executable H. J. Lu
  2005-04-30  0:38 ` How to avoid unnecessary R_IA64_FPTR64LSB in executable? James E Wilson
  0 siblings, 2 replies; 11+ messages in thread
From: H. J. Lu @ 2005-04-28  7:00 UTC (permalink / raw)
  To: binutils

The ia64 linker creates unnecessary R_IA64_FPTR64LSB relocations:

http://sources.redhat.com/bugzilla/show_bug.cgi?id=883

Basically, the ia64 linker creates R_IA64_FPTR64LSB relocations in
executable when there is any reference in DSO even though it is only
needed for dynamic R_IA64_FPTR64LSB relocations. I have 2 questions:

1. When we export a function in executable, whose function pointer is
used in executable and which is referenced by a DSO, can we create a
R_IA64_FPTR64LSB in executable only when there is a dynamic
R_IA64_FPTR64LSB reference? The only problem I can see is the different
version of the DSO may have dynamic R_IA64_FPTR64LSB reference. But
I think it is the same problem that the different version of the DSO 
may reference functions in executable which weren't referenced and
weren't exported before.
2. Assuming, we create a R_IA64_FPTR64LSB in executable only when
there is a dynamic R_IA64_FPTR64LSB relocation, how does linker
know there is a dynamic R_IA64_FPTR64LSB relocation? I am thinking to
allow the backend to read dynamic relocations after all input files
have been opened. The ia64 backend will have enough information to
decide what to do.


H.J.

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

* PATCH: Avoid unnecessary R_IA64_FPTR64LSB in executable
  2005-04-28  7:00 How to avoid unnecessary R_IA64_FPTR64LSB in executable? H. J. Lu
@ 2005-04-29  1:36 ` H. J. Lu
  2005-04-29  6:30   ` Richard Henderson
  2005-04-30  0:38 ` How to avoid unnecessary R_IA64_FPTR64LSB in executable? James E Wilson
  1 sibling, 1 reply; 11+ messages in thread
From: H. J. Lu @ 2005-04-29  1:36 UTC (permalink / raw)
  To: binutils; +Cc: wilson

On Wed, Apr 27, 2005 at 04:43:04PM -0700, H. J. Lu wrote:
> The ia64 linker creates unnecessary R_IA64_FPTR64LSB relocations:
> 
> http://sources.redhat.com/bugzilla/show_bug.cgi?id=883
> 
> Basically, the ia64 linker creates R_IA64_FPTR64LSB relocations in
> executable when there is any reference in DSO even though it is only
> needed for dynamic R_IA64_FPTR64LSB relocations. I have 2 questions:
> 
> 1. When we export a function in executable, whose function pointer is
> used in executable and which is referenced by a DSO, can we create a
> R_IA64_FPTR64LSB in executable only when there is a dynamic
> R_IA64_FPTR64LSB reference? The only problem I can see is the different
> version of the DSO may have dynamic R_IA64_FPTR64LSB reference. But
> I think it is the same problem that the different version of the DSO 
> may reference functions in executable which weren't referenced and
> weren't exported before.
> 2. Assuming, we create a R_IA64_FPTR64LSB in executable only when
> there is a dynamic R_IA64_FPTR64LSB relocation, how does linker
> know there is a dynamic R_IA64_FPTR64LSB relocation? I am thinking to
> allow the backend to read dynamic relocations after all input files
> have been opened. The ia64 backend will have enough information to
> decide what to do.
> 

This is the patch I come up with. I added check_dynamic_relocs to
check dynamic relocations. R_IA64_FPTR64LSB is used for the offical
function descriptors, which can only be accessed by R_IA64_FPTR64LSB.
Before we generate R_IA64_FPTR64LSB in executable, we check if there
are any R_IA64_FPTR64LSB relocations in DSO on that symbol. If there
is none, R_IA64_FPTR64LSB isn't needed.


H.J.
----
2005-04-28  H.J. Lu  <hongjiu.lu@intel.com>

	PR 883
	* elf-bfd.h (elf_backend_data): Add check_dynamic_relocs.

	* elflink.c (elf_link_read_relocs_from_section): Handle dynamic
	relocation.
	(elf_link_add_object_symbols): Call check_dynamic_relocs on
	dynamic library if the backend has check_dynamic_relocs.

	* elfxx-ia64.c (elfNN_ia64_link_hash_entry): Add need_ofd.
	(NEED_OFD): New macro.
	(elfNN_ia64_new_elf_hash_entry): Initialize need_ofd.
	(elfNN_ia64_hash_copy_indirect): Handle need_ofd.
	(elfNN_ia64_check_relocs): Set need_ofd for R_IA64_FPTRXXXXX.
	(elfNN_ia64_check_dynamic_relocs): New function.
	(allocate_fptr): Allocate if NEED_OFD is FALSE.
	(allocate_dynrel_entries): Check NEED_OFD before allocate.
	(elfNN_ia64_relocate_section): Call set_fptr_entry for
	R_IA64_LTOFF_FPTRXXXXX if NEED_OFD is FALSE.
	(elf_backend_check_dynamic_relocs): Defined.

	* elfxx-target.h (elf_backend_check_relocs): New. Provide
	default.
	(elfNN_bed): Initialize check_dynamic_relocs to
	elf_backend_check_relocs.


--- bfd/elf-bfd.h.dyn	2005-04-28 16:03:46.000000000 -0700
+++ bfd/elf-bfd.h	2005-04-28 16:03:47.000000000 -0700
@@ -704,6 +704,17 @@ struct elf_backend_data
     (bfd *abfd, struct bfd_link_info *info, asection *o,
      const Elf_Internal_Rela *relocs);
 
+  /* The CHECK_DYNAMIC_RELOCS function is called by the add_symbols
+     phase of the ELF backend linker.  It is called once for each
+     relocation section of a dynamic library, just after the symbols
+     for the object file have been added to the global linker hash
+     table.  The function must look through the relocs and do any
+     special handling required.  This generally isn't needed.  */
+  bfd_boolean (*check_dynamic_relocs)
+    (bfd *abfd, struct bfd_link_info *info,
+     const Elf_Internal_Shdr *hdr,
+     const Elf_Internal_Rela *relocs);
+
   /* 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
--- bfd/elflink.c.dyn	2005-04-28 16:03:47.000000000 -0700
+++ bfd/elflink.c	2005-04-28 16:03:47.000000000 -0700
@@ -2003,6 +2003,7 @@ elf_link_read_relocs_from_section (bfd *
   Elf_Internal_Rela *irela;
   Elf_Internal_Shdr *symtab_hdr;
   size_t nsyms;
+  bfd_boolean dynamic = abfd->flags & DYNAMIC;
 
   /* Position ourselves at the start of the section.  */
   if (bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0)
@@ -2012,7 +2013,10 @@ elf_link_read_relocs_from_section (bfd *
   if (bfd_bread (external_relocs, shdr->sh_size, abfd) != shdr->sh_size)
     return FALSE;
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  if (dynamic)
+    symtab_hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+  else
+    symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   nsyms = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
 
   bed = get_elf_backend_data (abfd);
@@ -2041,11 +2045,18 @@ elf_link_read_relocs_from_section (bfd *
 	r_symndx >>= 24;
       if ((size_t) r_symndx >= nsyms)
 	{
-	  (*_bfd_error_handler)
-	    (_("%B: bad reloc symbol index (0x%lx >= 0x%lx)"
-	       " for offset 0x%lx in section `%A'"),
-	     abfd, sec,
-	     (unsigned long) r_symndx, (unsigned long) nsyms, irela->r_offset);
+	  if (dynamic)
+	    (*_bfd_error_handler)
+	      (_("%B: bad reloc symbol index (0x%lx >= 0x%lx)"
+		 " for address 0x%lx"),
+	       abfd, (unsigned long) r_symndx,
+	       (unsigned long) nsyms, irela->r_offset);
+	  else
+	    (*_bfd_error_handler)
+	      (_("%B: bad reloc symbol index (0x%lx >= 0x%lx)"
+		 " for offset 0x%lx in section `%A'"),
+	       abfd, sec, (unsigned long) r_symndx,
+	       (unsigned long) nsyms, irela->r_offset);
 	  bfd_set_error (bfd_error_bad_value);
 	  return FALSE;
 	}
@@ -3192,8 +3203,6 @@ elf_link_add_object_symbols (bfd *abfd, 
   bfd_boolean (*add_symbol_hook)
     (bfd *, struct bfd_link_info *, Elf_Internal_Sym *,
      const char **, flagword *, asection **, bfd_vma *);
-  bfd_boolean (*check_relocs)
-    (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
   bfd_boolean (*check_directives)
     (bfd *, struct bfd_link_info *);
   bfd_boolean collect;
@@ -3215,6 +3224,7 @@ elf_link_add_object_symbols (bfd *abfd, 
   bfd_boolean add_needed;
   struct elf_link_hash_table * hash_table;
   bfd_size_type amt;
+  asection *section_list;
 
   hash_table = elf_hash_table (info);
 
@@ -3321,6 +3331,9 @@ elf_link_add_object_symbols (bfd *abfd, 
 	}
     }
 
+  /* Save the section list for check_dynamic_relocs.  */
+  section_list = abfd->sections;
+
   add_needed = TRUE;
   if (! dynamic)
     {
@@ -4437,38 +4450,102 @@ elf_link_add_object_symbols (bfd *abfd, 
 
      I have no idea how to handle linking PIC code into a file of a
      different format.  It probably can't be done.  */
-  check_relocs = get_elf_backend_data (abfd)->check_relocs;
-  if (! dynamic
-      && is_elf_hash_table (hash_table)
-      && hash_table->root.creator == abfd->xvec
-      && check_relocs != NULL)
+  if (is_elf_hash_table (hash_table)
+      && hash_table->root.creator == abfd->xvec)
     {
-      asection *o;
+      if (dynamic)
+	{
+	  bfd_boolean (*check_dynamic_relocs)
+	    (bfd *, struct bfd_link_info *,
+	     const Elf_Internal_Shdr *,
+	     const Elf_Internal_Rela *);
 
-      for (o = abfd->sections; o != NULL; o = o->next)
+	  check_dynamic_relocs
+	    = get_elf_backend_data (abfd)->check_dynamic_relocs;
+	  if (check_dynamic_relocs != NULL)
+	    {
+	      unsigned int i;
+
+	      for (i = 1; i < elf_numsections (abfd); i++)
+		{
+		  Elf_Internal_Shdr *hdr;
+		  Elf_Internal_Rela *internal_relocs;
+		  void *external_relocs;
+		  bfd_boolean ok;
+
+		  hdr = elf_elfsections (abfd)[i];
+		  if (hdr->sh_type != SHT_REL
+		      && hdr->sh_type != SHT_RELA)
+		    continue;
+
+		  internal_relocs = bfd_malloc (NUM_SHDR_ENTRIES (hdr)
+						* bed->s->int_rels_per_ext_rel
+						* sizeof (Elf_Internal_Rela));
+		  if (internal_relocs == NULL)
+		    goto error_return;
+
+		  external_relocs = bfd_malloc (hdr->sh_size);
+		  if (external_relocs == NULL)
+		    {
+		      free (internal_relocs);
+		      goto error_return;
+		    }
+
+		  if (!elf_link_read_relocs_from_section (abfd, NULL,
+							  hdr,
+							  external_relocs,
+							  internal_relocs))
+		    goto error_return;
+
+		  ok = (*check_dynamic_relocs) (abfd, info, hdr,
+						internal_relocs);
+
+		  free (internal_relocs);
+		  free (external_relocs);
+
+		  if (! ok)
+		    goto error_return;
+		}
+	    }
+	}
+      else
 	{
-	  Elf_Internal_Rela *internal_relocs;
-	  bfd_boolean ok;
+	  asection *o;
+	  bfd_boolean (*check_relocs)
+	    (bfd *, struct bfd_link_info *, asection *,
+	     const Elf_Internal_Rela *);
 
-	  if ((o->flags & SEC_RELOC) == 0
-	      || o->reloc_count == 0
-	      || ((info->strip == strip_all || info->strip == strip_debugger)
-		  && (o->flags & SEC_DEBUGGING) != 0)
-	      || bfd_is_abs_section (o->output_section))
-	    continue;
+	  check_relocs = get_elf_backend_data (abfd)->check_relocs;
+	  if (check_relocs != NULL)
+	    {
+	      for (o = section_list; o != NULL; o = o->next)
+		{
+		  Elf_Internal_Rela *internal_relocs;
+		  bfd_boolean ok;
 
-	  internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
-						       info->keep_memory);
-	  if (internal_relocs == NULL)
-	    goto error_return;
+		  if ((o->flags & SEC_RELOC) == 0
+		      || o->reloc_count == 0
+		      || ((info->strip == strip_all
+			   || info->strip == strip_debugger)
+			  && (o->flags & SEC_DEBUGGING) != 0)
+		      || bfd_is_abs_section (o->output_section))
+		    continue;
 
-	  ok = (*check_relocs) (abfd, info, o, internal_relocs);
+		  internal_relocs
+		    = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
+						 info->keep_memory);
+		  if (internal_relocs == NULL)
+		    goto error_return;
 
-	  if (elf_section_data (o)->relocs != internal_relocs)
-	    free (internal_relocs);
+		  ok = (*check_relocs) (abfd, info, o, internal_relocs);
 
-	  if (! ok)
-	    goto error_return;
+		  if (elf_section_data (o)->relocs != internal_relocs)
+		    free (internal_relocs);
+
+		  if (! ok)
+		    goto error_return;
+		}
+	    }
 	}
     }
 
--- bfd/elfxx-ia64.c.dyn	2005-04-28 16:03:46.000000000 -0700
+++ bfd/elfxx-ia64.c	2005-04-28 16:19:36.000000000 -0700
@@ -144,8 +144,15 @@ struct elfNN_ia64_link_hash_entry
 {
   struct elf_link_hash_entry root;
   struct elfNN_ia64_dyn_sym_info *info;
+  /* If this symbol needs the official function descriptor.  */
+  unsigned need_ofd : 1;
 };
 
+#define NEED_OFD(info, h) \
+   (((struct elfNN_ia64_link_hash_entry *)(h))->need_ofd	\
+    || !(info)->executable					\
+    || !SYMBOL_CALLS_LOCAL ((info), (h)))
+
 struct elfNN_ia64_link_hash_table
 {
   /* The main hash table.  */
@@ -1639,6 +1646,7 @@ elfNN_ia64_new_elf_hash_entry (entry, ta
 				     table, string));
 
   ret->info = NULL;
+  ret->need_ofd = 0;
   return (struct bfd_hash_entry *) ret;
 }
 
@@ -1689,6 +1697,8 @@ elfNN_ia64_hash_copy_indirect (bed, xdir
       ind->root.dynstr_index = 0;
     }
   BFD_ASSERT (ind->root.dynindx == -1);
+
+  dir->need_ofd |= ind->need_ofd;
 }
 
 static void
@@ -2321,7 +2331,11 @@ elfNN_ia64_check_relocs (abfd, info, sec
 	case R_IA64_FPTR64MSB:
 	case R_IA64_FPTR64LSB:
 	  if (info->shared || h)
-	    need_entry = NEED_FPTR | NEED_DYNREL;
+	    {
+	      need_entry = NEED_FPTR | NEED_DYNREL;
+	      if (h)
+		((struct elfNN_ia64_link_hash_entry *)h)->need_ofd = 1;
+	    }
 	  else
 	    need_entry = NEED_FPTR;
 	  dynrel_type = R_IA64_FPTRNNLSB;
@@ -2496,6 +2510,83 @@ elfNN_ia64_check_relocs (abfd, info, sec
   return TRUE;
 }
 
+static bfd_boolean
+elfNN_ia64_check_dynamic_relocs (bfd *abfd,
+				 struct bfd_link_info *info,
+				 const Elf_Internal_Shdr *hdr,
+				 const Elf_Internal_Rela *relocs)
+{
+  struct elfNN_ia64_link_hash_table *ia64_info;
+  const Elf_Internal_Rela *relend;
+  Elf_Internal_Shdr *symtab_hdr;
+  const Elf_Internal_Rela *rel;
+
+  if (info->relocatable)
+    return TRUE;
+
+  symtab_hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+  ia64_info = elfNN_ia64_hash_table (info);
+
+  relend = relocs + NUM_SHDR_ENTRIES (hdr);
+  for (rel = relocs; rel < relend; ++rel)
+    {
+      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
+      unsigned int r_type;
+      reloc_howto_type *howto;
+      long indx;
+
+      r_type = ELFNN_R_TYPE (rel->r_info);
+      switch (r_type)
+	{
+	case R_IA64_NONE:
+	case R_IA64_DIR32MSB:
+	case R_IA64_DIR32LSB:
+	case R_IA64_DIR64MSB:
+	case R_IA64_DIR64LSB:
+	case R_IA64_DTPMOD64MSB:
+	case R_IA64_DTPMOD64LSB:
+	case R_IA64_IPLTLSB:
+	case R_IA64_IPLTMSB:
+	case R_IA64_REL32MSB:
+	case R_IA64_REL32LSB:
+	case R_IA64_REL64MSB:
+	case R_IA64_REL64LSB:
+	case R_IA64_TPREL64MSB:
+	case R_IA64_TPREL64LSB:
+	  break;
+
+	case R_IA64_FPTR64I:
+	case R_IA64_FPTR32MSB:
+	case R_IA64_FPTR32LSB:
+	case R_IA64_FPTR64MSB:
+	case R_IA64_FPTR64LSB:
+	  indx = r_symndx - symtab_hdr->sh_info;
+
+	  if (indx >= 0)
+	    {
+	      struct elf_link_hash_entry *h;
+
+	      h = elf_sym_hashes (abfd)[indx];
+	      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;
+
+	      ((struct elfNN_ia64_link_hash_entry *)h)->need_ofd = 1;
+	    }
+	  break;
+
+	default:
+	  howto = lookup_howto (r_type);
+	  (*_bfd_error_handler)
+	    (_("%B: unsupported dynamic relocation `%s' in `%A'."),
+	     abfd, hdr->bfd_section, howto->name);
+	  break;
+	}
+    }
+
+  return TRUE;
+}
+
 /* For cleanliness, and potentially faster dynamic loading, allocate
    external GOT entries first.  */
 
@@ -2639,7 +2730,7 @@ allocate_fptr (dyn_i, data)
 
 	  dyn_i->want_fptr = 0;
 	}
-      else if (h == NULL || h->dynindx == -1)
+      else if (h == NULL || h->dynindx == -1 || !NEED_OFD (x->info, h))
 	{
 	  dyn_i->fptr_offset = x->ofs;
 	  x->ofs += 16;
@@ -2811,7 +2902,8 @@ allocate_dynrel_entries (dyn_i, data)
        && (dyn_i->want_got || dyn_i->want_gotx))
       || (dyn_i->want_ltoff_fptr
 	  && dyn_i->h
-	  && dyn_i->h->dynindx != -1))
+	  && dyn_i->h->dynindx != -1
+	  && NEED_OFD (x->info, dyn_i->h)))
     {
       if (!dyn_i->want_ltoff_fptr
 	  || !x->info->pie
@@ -4224,7 +4316,9 @@ elfNN_ia64_relocate_section (output_bfd,
 	    dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
 	    if (dyn_i->want_fptr)
 	      {
-		BFD_ASSERT (h == NULL || h->dynindx == -1);
+		BFD_ASSERT (h == NULL
+			    || h->dynindx == -1
+			    || !NEED_OFD (info, h));
 	        if (!undef_weak_ref)
 	          value = set_fptr_entry (output_bfd, info, dyn_i, value);
 		dynindx = -1;
@@ -5111,6 +5205,8 @@ elfNN_hpux_backend_symbol_processing (bf
 	elfNN_ia64_create_dynamic_sections
 #define elf_backend_check_relocs \
 	elfNN_ia64_check_relocs
+#define elf_backend_check_dynamic_relocs \
+	elfNN_ia64_check_dynamic_relocs
 #define elf_backend_adjust_dynamic_symbol \
 	elfNN_ia64_adjust_dynamic_symbol
 #define elf_backend_size_dynamic_sections \
--- bfd/elfxx-target.h.dyn	2005-03-02 11:54:22.000000000 -0800
+++ bfd/elfxx-target.h	2005-04-28 16:03:47.000000000 -0700
@@ -355,6 +355,9 @@
 #ifndef elf_backend_check_relocs
 #define elf_backend_check_relocs	0
 #endif
+#ifndef elf_backend_check_dynamic_relocs
+#define elf_backend_check_dynamic_relocs 0
+#endif
 #ifndef elf_backend_check_directives
 #define elf_backend_check_directives	0
 #endif
@@ -548,6 +551,7 @@ static const struct elf_backend_data elf
   elf_backend_create_dynamic_sections,
   elf_backend_omit_section_dynsym,
   elf_backend_check_relocs,
+  elf_backend_check_dynamic_relocs,
   elf_backend_check_directives,
   elf_backend_adjust_dynamic_symbol,
   elf_backend_always_size_sections,

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

* Re: PATCH: Avoid unnecessary R_IA64_FPTR64LSB in executable
  2005-04-29  1:36 ` PATCH: Avoid unnecessary R_IA64_FPTR64LSB in executable H. J. Lu
@ 2005-04-29  6:30   ` Richard Henderson
  2005-04-29  7:56     ` H. J. Lu
  0 siblings, 1 reply; 11+ messages in thread
From: Richard Henderson @ 2005-04-29  6:30 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils, wilson

On Thu, Apr 28, 2005 at 04:26:55PM -0700, H. J. Lu wrote:
> > 1. When we export a function in executable, whose function pointer is
> > used in executable and which is referenced by a DSO, can we create a
> > R_IA64_FPTR64LSB in executable only when there is a dynamic
> > R_IA64_FPTR64LSB reference?

No, we need one any time the symbol is dynamic.  Which does let you
eliminate quite a few.  But with --export-dynamic you can't just 
look for those that are referenced.



r~

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

* Re: PATCH: Avoid unnecessary R_IA64_FPTR64LSB in executable
  2005-04-29  6:30   ` Richard Henderson
@ 2005-04-29  7:56     ` H. J. Lu
  0 siblings, 0 replies; 11+ messages in thread
From: H. J. Lu @ 2005-04-29  7:56 UTC (permalink / raw)
  To: Richard Henderson; +Cc: binutils, wilson

On Thu, Apr 28, 2005 at 06:36:04PM -0700, Richard Henderson wrote:
> On Thu, Apr 28, 2005 at 04:26:55PM -0700, H. J. Lu wrote:
> > > 1. When we export a function in executable, whose function pointer is
> > > used in executable and which is referenced by a DSO, can we create a
> > > R_IA64_FPTR64LSB in executable only when there is a dynamic
> > > R_IA64_FPTR64LSB reference?
> 
> No, we need one any time the symbol is dynamic.  Which does let you
> eliminate quite a few.  But with --export-dynamic you can't just 
> look for those that are referenced.
> 

Do you have a testcase?  I thought you didn't need R_IA64_FPTR64LSB for
every dynamic function symbol and you only needed it for official
functon descriptor. As for --export-dynamic, I have to check if it
creates R_IA64_FPTR64LSB relocations for all pointers to function
symbols.


H.J.

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

* Re: How to avoid unnecessary R_IA64_FPTR64LSB in executable?
  2005-04-28  7:00 How to avoid unnecessary R_IA64_FPTR64LSB in executable? H. J. Lu
  2005-04-29  1:36 ` PATCH: Avoid unnecessary R_IA64_FPTR64LSB in executable H. J. Lu
@ 2005-04-30  0:38 ` James E Wilson
  2005-04-30 19:37   ` H. J. Lu
  1 sibling, 1 reply; 11+ messages in thread
From: James E Wilson @ 2005-04-30  0:38 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils

On Wed, 2005-04-27 at 16:43, H. J. Lu wrote:
> 1. When we export a function in executable, whose function pointer is
> used in executable and which is referenced by a DSO, can we create a
> R_IA64_FPTR64LSB in executable only when there is a dynamic
> R_IA64_FPTR64LSB reference?

I don't know if I can help with this thread.  I don't have enough
experience dealing with linker related issues.

However, it does occur to me to ask what happens with programs that use
dlopen.  You are assuming you can detect all DSO references at link
time, but can't we dlopen a library that wasn't initially linked in?  In
that case, you would have to create the FPTR64LSB reloc for anything
that might be usable from a DSO, regardless of whether we see a
reference at link time.  That seems to be what Richard meant when he
referred to --export-dynamic.

The Software Conventions and Runtime Architecture guide says an direct
dynamically-linked call effectively is handled the same as an indirect
call, which implies that it needs a function descriptor.  But I don't
think this means we need an official function descriptor.

I see that i_prot1 got added to the dynamic symbol table, even though
--export-dynamic wasn't used, simply because it was used in the so.so
library.  This presumably means a dlopen'ed library could also use
i_prot1.  Suppose that dlopen'ed library library takes the address of
i_prot1, and then this address gets compared with the one we took in
main.  We would have needed to create an official function descriptor
for this to work.  This implies that anything that ended up in the
dynamic symbol table needs an official function descriptor if there was
an FPTR reloc in the executable, even if there are no dynamic FPTR
relocs in any shared libraries referenced at the initial link time. 
Again, this seems to agree with what Richard said.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com


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

* Re: How to avoid unnecessary R_IA64_FPTR64LSB in executable?
  2005-04-30  0:38 ` How to avoid unnecessary R_IA64_FPTR64LSB in executable? James E Wilson
@ 2005-04-30 19:37   ` H. J. Lu
  2005-05-03  2:02     ` James E Wilson
  0 siblings, 1 reply; 11+ messages in thread
From: H. J. Lu @ 2005-04-30 19:37 UTC (permalink / raw)
  To: James E Wilson; +Cc: binutils

On Fri, Apr 29, 2005 at 12:20:35PM -0700, James E Wilson wrote:
> On Wed, 2005-04-27 at 16:43, H. J. Lu wrote:
> > 1. When we export a function in executable, whose function pointer is
> > used in executable and which is referenced by a DSO, can we create a
> > R_IA64_FPTR64LSB in executable only when there is a dynamic
> > R_IA64_FPTR64LSB reference?
> 
> I don't know if I can help with this thread.  I don't have enough
> experience dealing with linker related issues.
> 
> However, it does occur to me to ask what happens with programs that use
> dlopen.  You are assuming you can detect all DSO references at link
> time, but can't we dlopen a library that wasn't initially linked in?  In
> that case, you would have to create the FPTR64LSB reloc for anything
> that might be usable from a DSO, regardless of whether we see a
> reference at link time.  That seems to be what Richard meant when he
> referred to --export-dynamic.
> 
> The Software Conventions and Runtime Architecture guide says an direct
> dynamically-linked call effectively is handled the same as an indirect
> call, which implies that it needs a function descriptor.  But I don't
> think this means we need an official function descriptor.
> 
> I see that i_prot1 got added to the dynamic symbol table, even though
> --export-dynamic wasn't used, simply because it was used in the so.so
> library.  This presumably means a dlopen'ed library could also use
> i_prot1.  Suppose that dlopen'ed library library takes the address of
> i_prot1, and then this address gets compared with the one we took in
> main.  We would have needed to create an official function descriptor
> for this to work.  This implies that anything that ended up in the
> dynamic symbol table needs an official function descriptor if there was
> an FPTR reloc in the executable, even if there are no dynamic FPTR
> relocs in any shared libraries referenced at the initial link time. 
> Again, this seems to agree with what Richard said.

You are right. I forgot about the dlopened DSOs. The problem I am
trying to solve is we want to allow dlopened DSOs to access some
symbols in executable, which happen to be accessed via function
pointers in executable. The only way to do it is use --export-dynamic,
which leads to thousands of R_IA64_FPTR64LSB. We need a way to
selectively make some symbols in executable dynamic.

It turns out that 2 patches I submitted:

http://sourceware.org/ml/binutils/2005-04/msg00617.html
http://sourceware.org/ml/binutils/2005-04/msg00822.html

may be useful. Here is an updated patch. It supports exporting
selected symbols from a DSO or an executable with a version script.


H.J.
----
2005-04-30  H.J. Lu  <hongjiu.lu@intel.com>

	* elf-bfd.h (elf_link_hash_entry): Add forced_global.

	* elflink.c (bfd_elf_link_record_dynamic_symbol): Don't check
	symbol visibilty when we force a forced local symbol to global.
	(_bfd_elf_link_renumber_dynsyms): Move forced local symbols
	just before global ones.
	(_bfd_elf_link_assign_sym_version): When building shared
	library, set the forced_global field and make it global dynamic
	if a forced local symbol is marked as global. When building
	executable, make a symbol dynamic if it is marked global. Allow
	hiding symbols in executable.
	(elf_link_output_extsym): Handle forced_global.

--- bfd/elf-bfd.h.exec	2005-04-28 12:21:40.000000000 -0700
+++ bfd/elf-bfd.h	2005-04-29 23:30:28.000000000 -0700
@@ -155,6 +155,8 @@ struct elf_link_hash_entry
   unsigned int hidden : 1;
   /* Symbol was forced to local scope due to a version script file.  */
   unsigned int forced_local : 1;
+  /* Symbol was forced to global scope due to a version script file.  */
+  unsigned int forced_global : 1;
   /* Symbol was marked during garbage collection.  */
   unsigned int mark : 1;
   /* Symbol is referenced by a non-GOT/non-PLT relocation.  This is
--- bfd/elflink.c.exec	2005-04-29 23:30:28.000000000 -0700
+++ bfd/elflink.c	2005-04-30 00:02:27.000000000 -0700
@@ -394,22 +394,24 @@ bfd_elf_link_record_dynamic_symbol (stru
       /* XXX: The ABI draft says the linker must turn hidden and
 	 internal symbols into STB_LOCAL symbols when producing the
 	 DSO. However, if ld.so honors st_other in the dynamic table,
-	 this would not be necessary.  */
-      switch (ELF_ST_VISIBILITY (h->other))
-	{
-	case STV_INTERNAL:
-	case STV_HIDDEN:
-	  if (h->root.type != bfd_link_hash_undefined
-	      && h->root.type != bfd_link_hash_undefweak)
-	    {
-	      h->forced_local = 1;
-	      if (!elf_hash_table (info)->is_relocatable_executable)
-		return TRUE;
-	    }
+	 this would not be necessary.  Don't check symbol visibilty
+	 when we force a forced local symbol to global.  */
+      if (!h->forced_global)
+	switch (ELF_ST_VISIBILITY (h->other))
+	  {
+	  case STV_INTERNAL:
+	  case STV_HIDDEN:
+	    if (h->root.type != bfd_link_hash_undefined
+		&& h->root.type != bfd_link_hash_undefweak)
+	      {
+		h->forced_local = 1;
+		if (!elf_hash_table (info)->is_relocatable_executable)
+		  return TRUE;
+	      }
 
-	default:
-	  break;
-	}
+	  default:
+	    break;
+	  }
 
       h->dynindx = elf_hash_table (info)->dynsymcount;
       ++elf_hash_table (info)->dynsymcount;
@@ -719,9 +721,9 @@ _bfd_elf_link_omit_section_dynsym (bfd *
 }
 
 /* Assign dynsym indices.  In a shared library we generate a section
-   symbol for each output section, which come first.  Next come symbols
-   which have been forced to local binding.  Then all of the back-end
-   allocated local dynamic syms, followed by the rest of the global
+   symbol for each output section, which come first.  Next come all of
+   the back-end allocated local dynamic syms.  Then symbols which have
+   been forced to local binding, followed by the rest of the global
    symbols.  */
 
 static unsigned long
@@ -743,10 +745,6 @@ _bfd_elf_link_renumber_dynsyms (bfd *out
     }
   *section_sym_count = dynsymcount;
 
-  elf_link_hash_traverse (elf_hash_table (info),
-			  elf_link_renumber_local_hash_table_dynsyms,
-			  &dynsymcount);
-
   if (elf_hash_table (info)->dynlocal)
     {
       struct elf_link_local_dynamic_entry *p;
@@ -755,6 +753,10 @@ _bfd_elf_link_renumber_dynsyms (bfd *out
     }
 
   elf_link_hash_traverse (elf_hash_table (info),
+			  elf_link_renumber_local_hash_table_dynsyms,
+			  &dynsymcount);
+
+  elf_link_hash_traverse (elf_hash_table (info),
 			  elf_link_renumber_hash_table_dynsyms,
 			  &dynsymcount);
 
@@ -1745,6 +1747,7 @@ _bfd_elf_link_assign_sym_version (struct
   struct elf_info_failed eif;
   char *p;
   bfd_size_type amt;
+  bfd_boolean global;
 
   sinfo = data;
   info = sinfo->info;
@@ -1767,6 +1770,9 @@ _bfd_elf_link_assign_sym_version (struct
   if (!h->def_regular)
     return TRUE;
 
+  /* Check if a symbol is marked as global in version script.  */
+  global = FALSE;
+
   bed = get_elf_backend_data (sinfo->output_bfd);
   p = strchr (h->root.root.string, ELF_VER_CHR);
   if (p != NULL && h->verinfo.vertree == NULL)
@@ -1825,10 +1831,11 @@ _bfd_elf_link_assign_sym_version (struct
 		  d = (*t->match) (&t->locals, NULL, alc);
 		  if (d != NULL
 		      && h->dynindx != -1
-		      && info->shared
 		      && ! info->export_dynamic)
 		    (*bed->elf_backend_hide_symbol) (info, h, TRUE);
 		}
+	      else if (d)
+		global = TRUE;
 
 	      free (alc);
 	      break;
@@ -1919,6 +1926,7 @@ _bfd_elf_link_assign_sym_version (struct
 		    h->verinfo.vertree = t;
 		    local_ver = NULL;
 		    d->script = 1;
+		    global = TRUE;
 		    break;
 		  }
 	      if (d != NULL)
@@ -1952,14 +1960,24 @@ _bfd_elf_link_assign_sym_version (struct
 	{
 	  h->verinfo.vertree = local_ver;
 	  if (h->dynindx != -1
-	      && info->shared
 	      && ! info->export_dynamic)
 	    {
+	      global = FALSE;
 	      (*bed->elf_backend_hide_symbol) (info, h, TRUE);
 	    }
 	}
     }
 
+  if (global && (info->executable || h->forced_local))
+    {
+      if (h->forced_local)
+	h->forced_global = 1;
+
+      if (h->dynindx == -1
+	  && ! bfd_elf_link_record_dynamic_symbol (info, h))
+	return FALSE;
+    }
+
   return TRUE;
 }
 \f
@@ -6392,12 +6410,12 @@ elf_link_output_extsym (struct elf_link_
   /* Decide whether to output this symbol in this pass.  */
   if (eoinfo->localsyms)
     {
-      if (!h->forced_local)
+      if (!h->forced_local || h->forced_global)
 	return TRUE;
     }
   else
     {
-      if (h->forced_local)
+      if (h->forced_local && !h->forced_global)
 	return TRUE;
     }
 
@@ -6427,6 +6445,7 @@ elf_link_output_extsym (struct elf_link_
   if (! finfo->info->relocatable
       && (! finfo->info->shared)
       && h->forced_local
+      && !h->forced_global
       && h->ref_dynamic
       && !h->dynamic_def
       && !h->dynamic_weak
@@ -6480,7 +6499,14 @@ elf_link_output_extsym (struct elf_link_
   sym.st_value = 0;
   sym.st_size = h->size;
   sym.st_other = h->other;
-  if (h->forced_local)
+  if (h->forced_global)
+    {
+      /* A forced global symbol has the default visibility.  */
+      sym.st_other
+	= STV_DEFAULT | (h->other & ~ ELF_ST_VISIBILITY (-1));
+      sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
+    }
+  else if (h->forced_local)
     sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type);
   else if (h->root.type == bfd_link_hash_undefweak
 	   || h->root.type == bfd_link_hash_defweak)

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

* Re: How to avoid unnecessary R_IA64_FPTR64LSB in executable?
  2005-04-30 19:37   ` H. J. Lu
@ 2005-05-03  2:02     ` James E Wilson
  2005-05-03  2:53       ` Allow linker script on executable and hidden symbol H. J. Lu
  0 siblings, 1 reply; 11+ messages in thread
From: James E Wilson @ 2005-05-03  2:02 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils

On Sat, 2005-04-30 at 00:18, H. J. Lu wrote:
> It turns out that 2 patches I submitted:
> http://sourceware.org/ml/binutils/2005-04/msg00617.html
> http://sourceware.org/ml/binutils/2005-04/msg00822.html

The first patch is for turning hidden protected symbols into global
symbols.  The thread says that this will break function pointer
comparisons.  This doesn't seem like a good idea.  Nor does it seem
necessary to fix this particular problem.

The second patch is for applying a version script to an executable
instead of a shared library, so that you can globalize a symbol in an
executable.  This seems harmless enough, and seems sufficient to solve
the problem.  It is adding a new feature that doesn't seem to conflict
with any existing ones.  However, we probably need some documentation
updates.  The docs only talk about using version scripts with shared
libraries.  What exactly does it mean to apply a version script to an
executable?  Does specifying a version number in the version script do
anything?  I don't think it does.  Perhaps all we need is to modify the
paragraph that starts "Node name can be omited ..." to mention that this
form can also be used when linking executables.  Should we add some
checking code here maybe?  I.e. complain if !info->shared and there is a
version node name?  That might help catch version script mistakes.

This is getting a bit far afield from what I normally review, as there
is no longer any IA-64 specific parts to this patch, and it is in the
linker which is the part that I understand the least.  It would be
useful to have some second opinions here.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com


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

* Allow linker script on executable and hidden symbol
  2005-05-03  2:02     ` James E Wilson
@ 2005-05-03  2:53       ` H. J. Lu
  2005-05-05 19:26         ` H. J. Lu
  0 siblings, 1 reply; 11+ messages in thread
From: H. J. Lu @ 2005-05-03  2:53 UTC (permalink / raw)
  To: James E Wilson; +Cc: binutils

On Mon, May 02, 2005 at 07:02:41PM -0700, James E Wilson wrote:
> On Sat, 2005-04-30 at 00:18, H. J. Lu wrote:
> > It turns out that 2 patches I submitted:
> > http://sourceware.org/ml/binutils/2005-04/msg00617.html
> > http://sourceware.org/ml/binutils/2005-04/msg00822.html
> 
> The first patch is for turning hidden protected symbols into global
> symbols.  The thread says that this will break function pointer
> comparisons.  This doesn't seem like a good idea.  Nor does it seem
> necessary to fix this particular problem.

When you mark a symbol hidden, it is done on purpose. The only
reasonable way to get a function pointer of a hidden symbol is using
a function call. This is similar to -Bsymbloc. The differences are
you can do it on selective symbols and compiler can take advantage of
it.

> 
> The second patch is for applying a version script to an executable
> instead of a shared library, so that you can globalize a symbol in an
> executable.  This seems harmless enough, and seems sufficient to solve
> the problem.  It is adding a new feature that doesn't seem to conflict
> with any existing ones.  However, we probably need some documentation
> updates.  The docs only talk about using version scripts with shared
> libraries.  What exactly does it mean to apply a version script to an
> executable?  Does specifying a version number in the version script do
> anything?  I don't think it does.  Perhaps all we need is to modify the
> paragraph that starts "Node name can be omited ..." to mention that this
> form can also be used when linking executables.  Should we add some
> checking code here maybe?  I.e. complain if !info->shared and there is a
> version node name?  That might help catch version script mistakes.

I will give it a try.

> 
> This is getting a bit far afield from what I normally review, as there
> is no longer any IA-64 specific parts to this patch, and it is in the
> linker which is the part that I understand the least.  It would be
> useful to have some second opinions here.


Thanks.


H.J.

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

* Re: Allow linker script on executable and hidden symbol
  2005-05-03  2:53       ` Allow linker script on executable and hidden symbol H. J. Lu
@ 2005-05-05 19:26         ` H. J. Lu
  2005-05-05 22:24           ` James E Wilson
  0 siblings, 1 reply; 11+ messages in thread
From: H. J. Lu @ 2005-05-05 19:26 UTC (permalink / raw)
  To: James E Wilson; +Cc: binutils

On Mon, May 02, 2005 at 07:53:25PM -0700, H. J. Lu wrote:
> On Mon, May 02, 2005 at 07:02:41PM -0700, James E Wilson wrote:
> > On Sat, 2005-04-30 at 00:18, H. J. Lu wrote:
> > > It turns out that 2 patches I submitted:
> > > http://sourceware.org/ml/binutils/2005-04/msg00617.html
> > > http://sourceware.org/ml/binutils/2005-04/msg00822.html
> > 
> > The first patch is for turning hidden protected symbols into global
> > symbols.  The thread says that this will break function pointer
> > comparisons.  This doesn't seem like a good idea.  Nor does it seem
> > necessary to fix this particular problem.
> 
> When you mark a symbol hidden, it is done on purpose. The only
> reasonable way to get a function pointer of a hidden symbol is using
> a function call. This is similar to -Bsymbloc. The differences are
> you can do it on selective symbols and compiler can take advantage of
> it.
> 
> > 
> > The second patch is for applying a version script to an executable
> > instead of a shared library, so that you can globalize a symbol in an
> > executable.  This seems harmless enough, and seems sufficient to solve
> > the problem.  It is adding a new feature that doesn't seem to conflict
> > with any existing ones.  However, we probably need some documentation
> > updates.  The docs only talk about using version scripts with shared
> > libraries.  What exactly does it mean to apply a version script to an
> > executable?  Does specifying a version number in the version script do
> > anything?  I don't think it does.  Perhaps all we need is to modify the
> > paragraph that starts "Node name can be omited ..." to mention that this
> > form can also be used when linking executables.  Should we add some
> > checking code here maybe?  I.e. complain if !info->shared and there is a
> > version node name?  That might help catch version script mistakes.
> 
> I will give it a try.
> 

Here is the updated patch.


H.J.
----
bfd/

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

	* elf-bfd.h (elf_link_hash_entry): Add forced_global.

	* elflink.c (bfd_elf_link_record_dynamic_symbol): Don't check
	symbol visibilty when we force a forced local symbol to global.
	(_bfd_elf_link_renumber_dynsyms): Move forced local symbols
	just before global ones.
	(_bfd_elf_link_assign_sym_version): When building shared
	library, set the forced_global field and make it global dynamic
	if a forced local symbol is marked as global. When building
	executable, make a symbol dynamic if it is marked global.
	(elf_link_output_extsym): Handle forced_global.

ld/

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

	* ld.texinfo: Document similarity between version script and
	--export-dynamicr/-Bsymbolic.

	* ldlang.c (lang_final): Don't allow named version tag on
	executables.

--- binutils/bfd/elf-bfd.h.exec	2005-05-05 07:44:33.000000000 -0700
+++ binutils/bfd/elf-bfd.h	2005-05-05 10:53:45.000000000 -0700
@@ -155,6 +155,8 @@ struct elf_link_hash_entry
   unsigned int hidden : 1;
   /* Symbol was forced to local scope due to a version script file.  */
   unsigned int forced_local : 1;
+  /* Symbol was forced to global scope due to a version script file.  */
+  unsigned int forced_global : 1;
   /* Symbol was marked during garbage collection.  */
   unsigned int mark : 1;
   /* Symbol is referenced by a non-GOT/non-PLT relocation.  This is
--- binutils/bfd/elflink.c.exec	2005-05-05 10:52:50.000000000 -0700
+++ binutils/bfd/elflink.c	2005-05-05 10:53:45.000000000 -0700
@@ -375,22 +375,24 @@ bfd_elf_link_record_dynamic_symbol (stru
       /* XXX: The ABI draft says the linker must turn hidden and
 	 internal symbols into STB_LOCAL symbols when producing the
 	 DSO. However, if ld.so honors st_other in the dynamic table,
-	 this would not be necessary.  */
-      switch (ELF_ST_VISIBILITY (h->other))
-	{
-	case STV_INTERNAL:
-	case STV_HIDDEN:
-	  if (h->root.type != bfd_link_hash_undefined
-	      && h->root.type != bfd_link_hash_undefweak)
-	    {
-	      h->forced_local = 1;
-	      if (!elf_hash_table (info)->is_relocatable_executable)
-		return TRUE;
-	    }
+	 this would not be necessary.  Don't check symbol visibilty
+	 when we force a forced local symbol to global.  */
+      if (!h->forced_global)
+	switch (ELF_ST_VISIBILITY (h->other))
+	  {
+	  case STV_INTERNAL:
+	  case STV_HIDDEN:
+	    if (h->root.type != bfd_link_hash_undefined
+		&& h->root.type != bfd_link_hash_undefweak)
+	      {
+		h->forced_local = 1;
+		if (!elf_hash_table (info)->is_relocatable_executable)
+		  return TRUE;
+	      }
 
-	default:
-	  break;
-	}
+	  default:
+	    break;
+	  }
 
       h->dynindx = elf_hash_table (info)->dynsymcount;
       ++elf_hash_table (info)->dynsymcount;
@@ -700,9 +702,9 @@ _bfd_elf_link_omit_section_dynsym (bfd *
 }
 
 /* Assign dynsym indices.  In a shared library we generate a section
-   symbol for each output section, which come first.  Next come symbols
-   which have been forced to local binding.  Then all of the back-end
-   allocated local dynamic syms, followed by the rest of the global
+   symbol for each output section, which come first.  Next come all of
+   the back-end allocated local dynamic syms.  Then symbols which have
+   been forced to local binding, followed by the rest of the global
    symbols.  */
 
 static unsigned long
@@ -724,10 +726,6 @@ _bfd_elf_link_renumber_dynsyms (bfd *out
     }
   *section_sym_count = dynsymcount;
 
-  elf_link_hash_traverse (elf_hash_table (info),
-			  elf_link_renumber_local_hash_table_dynsyms,
-			  &dynsymcount);
-
   if (elf_hash_table (info)->dynlocal)
     {
       struct elf_link_local_dynamic_entry *p;
@@ -736,6 +734,10 @@ _bfd_elf_link_renumber_dynsyms (bfd *out
     }
 
   elf_link_hash_traverse (elf_hash_table (info),
+			  elf_link_renumber_local_hash_table_dynsyms,
+			  &dynsymcount);
+
+  elf_link_hash_traverse (elf_hash_table (info),
 			  elf_link_renumber_hash_table_dynsyms,
 			  &dynsymcount);
 
@@ -1696,6 +1698,7 @@ _bfd_elf_link_assign_sym_version (struct
   struct elf_info_failed eif;
   char *p;
   bfd_size_type amt;
+  bfd_boolean global;
 
   sinfo = data;
   info = sinfo->info;
@@ -1718,6 +1721,9 @@ _bfd_elf_link_assign_sym_version (struct
   if (!h->def_regular)
     return TRUE;
 
+  /* Check if a symbol is marked as global in version script.  */
+  global = FALSE;
+
   bed = get_elf_backend_data (sinfo->output_bfd);
   p = strchr (h->root.root.string, ELF_VER_CHR);
   if (p != NULL && h->verinfo.vertree == NULL)
@@ -1779,6 +1785,8 @@ _bfd_elf_link_assign_sym_version (struct
 		      && ! info->export_dynamic)
 		    (*bed->elf_backend_hide_symbol) (info, h, TRUE);
 		}
+	      else if (d)
+		global = TRUE;
 
 	      free (alc);
 	      break;
@@ -1869,6 +1877,7 @@ _bfd_elf_link_assign_sym_version (struct
 		    h->verinfo.vertree = t;
 		    local_ver = NULL;
 		    d->script = 1;
+		    global = TRUE;
 		    break;
 		  }
 	      if (d != NULL)
@@ -1904,11 +1913,22 @@ _bfd_elf_link_assign_sym_version (struct
 	  if (h->dynindx != -1
 	      && ! info->export_dynamic)
 	    {
+	      global = FALSE;
 	      (*bed->elf_backend_hide_symbol) (info, h, TRUE);
 	    }
 	}
     }
 
+  if (global && (info->executable || h->forced_local))
+    {
+      if (h->forced_local)
+	h->forced_global = 1;
+
+      if (h->dynindx == -1
+	  && ! bfd_elf_link_record_dynamic_symbol (info, h))
+	return FALSE;
+    }
+
   return TRUE;
 }
 \f
@@ -6337,12 +6357,12 @@ elf_link_output_extsym (struct elf_link_
   /* Decide whether to output this symbol in this pass.  */
   if (eoinfo->localsyms)
     {
-      if (!h->forced_local)
+      if (!h->forced_local || h->forced_global)
 	return TRUE;
     }
   else
     {
-      if (h->forced_local)
+      if (h->forced_local && !h->forced_global)
 	return TRUE;
     }
 
@@ -6372,6 +6392,7 @@ elf_link_output_extsym (struct elf_link_
   if (! finfo->info->relocatable
       && (! finfo->info->shared)
       && h->forced_local
+      && !h->forced_global
       && h->ref_dynamic
       && !h->dynamic_def
       && !h->dynamic_weak
@@ -6425,7 +6446,14 @@ elf_link_output_extsym (struct elf_link_
   sym.st_value = 0;
   sym.st_size = h->size;
   sym.st_other = h->other;
-  if (h->forced_local)
+  if (h->forced_global)
+    {
+      /* A forced global symbol has the default visibility.  */
+      sym.st_other
+	= STV_DEFAULT | (h->other & ~ ELF_ST_VISIBILITY (-1));
+      sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
+    }
+  else if (h->forced_local)
     sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type);
   else if (h->root.type == bfd_link_hash_undefweak
 	   || h->root.type == bfd_link_hash_defweak)
--- binutils/ld/ld.texinfo.exec	2005-04-19 10:43:06.000000000 -0700
+++ binutils/ld/ld.texinfo	2005-05-05 12:18:44.000000000 -0700
@@ -476,11 +476,10 @@ mentioned in the link.
 If you use @code{dlopen} to load a dynamic object which needs to refer
 back to the symbols defined by the program, rather than some other
 dynamic object, then you will probably need to use this option when
-linking the program itself.
-
-You can also use the version script to control what symbols should
-be added to the dynamic symbol table if the output format supports it.
-See the description of @samp{--version-script} in @ref{VERSION}.
+linking the program itself.  If the output format supports the version
+script, you can also use it to add the symbols needed by the dynamic
+object to the dynamic symbol table.  See the description of
+@samp{--version-script} in @ref{VERSION}.
 
 @ifclear SingleFormat
 @cindex big-endian objects
@@ -1057,7 +1056,10 @@ When creating a shared library, bind ref
 definition within the shared library, if any.  Normally, it is possible
 for a program linked against a shared library to override the definition
 within the shared library.  This option is only meaningful on ELF
-platforms which support shared libraries.
+platforms which support shared libraries.  You can also use the version
+script to control which symbols should be bound to the definitions
+within the shared library.  See the description of
+@samp{--version-script} in @ref{VERSION}.
 
 @kindex --check-sections
 @kindex --no-check-sections
@@ -4257,12 +4259,22 @@ However, this would be a confusing way t
 Node name can be omited, provided it is the only version node
 in the version script.  Such version script doesn't assign any versions to
 symbols, only selects which symbols will be globally visible out and which
-won't.
+won't.  It can be used on executables to control which symbols will be
+exported and which won't.  When it is used to export symbols in
+executables, it is similar to @samp{--export-dynamic}, except for that
+symbols can be exported selectively with a version script.
 
 @smallexample
 @{ global: foo; bar; local: *; @};
 @end smallexample
 
+When a hidden symbol in a shared library is listed as global in a
+version script, its reference will be bound to the definition within
+the shared library and it will be exported.  It is similar to
+@samp{-Bsymbolic}, except for that symbols can be selectively bound
+their definitions.  If compiler is aware of symbol visibility, it can
+perform optimization which can't be done with @samp{-Bsymbolic} alone.
+
 When you link an application against a shared library that has versioned
 symbols, the application itself knows which version of each symbol it
 requires, and it also knows which version nodes it needs from each
--- binutils/ld/ldlang.c.exec	2005-05-05 10:53:45.000000000 -0700
+++ binutils/ld/ldlang.c	2005-05-05 11:20:33.000000000 -0700
@@ -5150,9 +5150,20 @@ lang_enter_output_section_statement (con
 void
 lang_final (void)
 {
-  lang_output_statement_type *new =
-    new_stat (lang_output_statement, stat_ptr);
+  lang_output_statement_type *new;
 
+  /* Check if version tag is valid for executable.  */
+  if (link_info.executable)
+    {
+      struct bfd_elf_version_tree *t;
+
+      for (t = lang_elf_version_info; t; t = t->next)
+	if (t->name [0] != '\0')
+	  einfo (_("%F%P: Invalid version tag `%s'. Only anonymous "
+		   "version tag is allowed in executable.\n"), t->name);
+    }
+
+  new = new_stat (lang_output_statement, stat_ptr);
   new->name = output_filename;
 }
 

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

* Re: Allow linker script on executable and hidden symbol
  2005-05-05 19:26         ` H. J. Lu
@ 2005-05-05 22:24           ` James E Wilson
  2005-05-05 23:25             ` H. J. Lu
  0 siblings, 1 reply; 11+ messages in thread
From: James E Wilson @ 2005-05-05 22:24 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils

On Thu, 2005-05-05 at 12:20, H. J. Lu wrote:
> Here is the updated patch.

The executable/version script part of this looks much better to me now. 
You have docs, and a linker consistency check.

However, this patch still includes the stuff for forcibly exporting
hidden variables.  Alan Modra objected to that, and pointed out that we
can get incorrect code in this case.  I've never used hidden variables,
and know little about how they work, but I do know that I should not be
overruling Alan when it comes to binutils decisions like this.  Maybe
you need to discuss this with him a bit more.

I think I see the point of the change.  -Bsymbolic affects all
variables, and you want a way to change the binding of individual
variables.  So effectively this is the same problem as the other part of
the patch.  Applying a linker script to an executable allows you to
changing binding of individual variables, whereas --export-dynamic
affects all of them.

However, that still leaves the question of whether we can get incorrect
code, which doesn't seem to have been resolved.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com


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

* Re: Allow linker script on executable and hidden symbol
  2005-05-05 22:24           ` James E Wilson
@ 2005-05-05 23:25             ` H. J. Lu
  0 siblings, 0 replies; 11+ messages in thread
From: H. J. Lu @ 2005-05-05 23:25 UTC (permalink / raw)
  To: James E Wilson; +Cc: binutils

On Thu, May 05, 2005 at 03:06:42PM -0700, James E Wilson wrote:
> On Thu, 2005-05-05 at 12:20, H. J. Lu wrote:
> > Here is the updated patch.
> 
> The executable/version script part of this looks much better to me now. 
> You have docs, and a linker consistency check.
> 
> However, this patch still includes the stuff for forcibly exporting
> hidden variables.  Alan Modra objected to that, and pointed out that we
> can get incorrect code in this case.  I've never used hidden variables,
> and know little about how they work, but I do know that I should not be
> overruling Alan when it comes to binutils decisions like this.  Maybe
> you need to discuss this with him a bit more.
> 
> I think I see the point of the change.  -Bsymbolic affects all
> variables, and you want a way to change the binding of individual
> variables.  So effectively this is the same problem as the other part of
> the patch.  Applying a linker script to an executable allows you to
> changing binding of individual variables, whereas --export-dynamic
> affects all of them.
> 
> However, that still leaves the question of whether we can get incorrect
> code, which doesn't seem to have been resolved.

My view is it generats the same code as -Bsymbolic. If we allow
-Bsymbolic to generate "incorrect" code on all symbols, why not do it
selectively?


H.J.

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

end of thread, other threads:[~2005-05-05 22:46 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-04-28  7:00 How to avoid unnecessary R_IA64_FPTR64LSB in executable? H. J. Lu
2005-04-29  1:36 ` PATCH: Avoid unnecessary R_IA64_FPTR64LSB in executable H. J. Lu
2005-04-29  6:30   ` Richard Henderson
2005-04-29  7:56     ` H. J. Lu
2005-04-30  0:38 ` How to avoid unnecessary R_IA64_FPTR64LSB in executable? James E Wilson
2005-04-30 19:37   ` H. J. Lu
2005-05-03  2:02     ` James E Wilson
2005-05-03  2:53       ` Allow linker script on executable and hidden symbol H. J. Lu
2005-05-05 19:26         ` H. J. Lu
2005-05-05 22:24           ` James E Wilson
2005-05-05 23:25             ` 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).