public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: "H. J. Lu" <hjl@lucon.org>
To: Michael Matz <matz@suse.de>
Cc: binutils@sources.redhat.com
Subject: RFC: Add dynamic list to version script
Date: Mon, 24 Jul 2006 22:27:00 -0000	[thread overview]
Message-ID: <20060724221020.GA22024@lucon.org> (raw)

On Tue, Jul 18, 2006 at 06:10:18PM +0200, Michael Matz wrote:
> Hi,
> 
> On Sun, 16 Jul 2006, H. J. Lu wrote:
> 
> > ld -shared -Bsymbolic will reduce number of dynamic relocations in
> > a shared library. Unfortunately, it won't work correctly with C++
> > exception and maybe other language features.
> > 
> > However, I think it is possible to make -shared -Bsymbolic to work
> > for C++ by providing a way to specify a list of symbols which must
> > be dynamic. We then can do
> > 
> > # g++ -Wl,-Bsymbolic -shared -xxx "list of dynamic symbols" -o libfoo.so ...
> > 
> > and libfoo.so written in C++ will work correctly with much fewer dynamic
> > relocations.
> 
> Yes, I'd like that too (actually a customer of us).  There is some 
> precedent set by the HP-UX linker (and I believe the Solaris linker has 
> that too).  Actually I would make -xxx (whatever the final name would be) 
> accept a list of globs, not just a list of symbols.  Then you simply can 
> say -xxx "_ZTS*,_ZTI*" and have the typeinfo symbols and names exported, 
> while all others are bound symbolically.
> 
> 

Here is a prototype, which added dynamic list to version script. I used

{
dynamic:
  extern "C++"
  {
    *typeinfo*;
  };
};

It seems to work correctly with execptions between shared C++ libraries.


H.J.
-----
bfd/

2006-07-24  H.J. Lu  <hongjiu.lu@intel.com>

	* elf-bfd.h (elf_link_hash_entry): Add a dynamic field.
	(bfd_elf_link_mark_dynamic_symbol): New.

	* elf32-i386.c (elf_i386_check_relocs): Also check the dynamic
	field.
	(elf_i386_relocate_section): Likewise.
	* elf64-x86-64.c (elf64_x86_64_check_relocs): Likewise.
	(elf64_x86_64_relocate_section): Likewise.
	* elflink.c (_bfd_elf_merge_symbol): Likewise.
	(_bfd_elf_fix_symbol_flags): Likewise.
	(_bfd_elf_dynamic_symbol_p): Likewise.
	(_bfd_elf_symbol_refs_local_p): Likewise.
	* elfxx-ia64.c (elfNN_ia64_check_relocs): Likewise.

	* elflink.c (bfd_elf_link_mark_dynamic_symbol): New.
	(bfd_elf_record_link_assignment): Call
	bfd_elf_link_mark_dynamic_symbol on new entry.
	(_bfd_elf_merge_symbol): Likewise.
	(_bfd_elf_export_symbol): Return if the symbol isn't exported.
	(_bfd_elf_link_assign_sym_version): Don't hide a symbol if it
	is marked dynamic.
	(bfd_elf_size_dynamic_sections): Updated.

include/

2006-07-24  H.J. Lu  <hongjiu.lu@intel.com>

	* bfdlink.h (bfd_elf_dynamic_list): New.
	(bfd_link_info): Add a dynamic field.

	* ld.texinfo: Updated.

	* ldgram.y: Support dynamic list.
	* ldlex.l: Likewise.

	* ldlang.c (lang_register_vers_node): Handle dynamic list.
	(lang_new_dynamic_list): New.
	* ldlang.h (lang_new_dynamic_list): Likewise.

	* ldmain.c (main): Initialize link_info.dynamic.

--- binutils/bfd/elf-bfd.h.dynamic	2006-07-18 13:26:51.000000000 -0700
+++ binutils/bfd/elf-bfd.h	2006-07-24 12:40:19.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 be dynamic due to a version script file.  */
+  unsigned int dynamic : 1;
   /* Symbol was marked during garbage collection.  */
   unsigned int mark : 1;
   /* Symbol is referenced by a non-GOT/non-PLT relocation.  This is
@@ -1833,6 +1835,9 @@ extern bfd_boolean bfd_elf_link_record_d
 extern int bfd_elf_link_record_local_dynamic_symbol
   (struct bfd_link_info *, bfd *, long);
 
+extern void bfd_elf_link_mark_dynamic_symbol
+  (struct bfd_link_info *, struct elf_link_hash_entry *);
+
 extern bfd_boolean _bfd_elf_close_and_cleanup
   (bfd *);
 
--- binutils/bfd/elf32-i386.c.dynamic	2006-07-11 12:53:42.000000000 -0700
+++ binutils/bfd/elf32-i386.c	2006-07-24 13:42:00.000000000 -0700
@@ -1151,6 +1151,8 @@ elf_i386_check_relocs (bfd *abfd,
 	       && (r_type != R_386_PC32
 		   || (h != NULL
 		       && (! info->symbolic
+			   || ! info->dynamic
+			   || h->dynamic
 			   || h->root.type == bfd_link_hash_defweak
 			   || !h->def_regular))))
 	      || (ELIMINATE_COPY_RELOCS
@@ -2630,6 +2632,8 @@ elf_i386_relocate_section (bfd *output_b
 		       && (r_type == R_386_PC32
 			   || !info->shared
 			   || !info->symbolic
+			   || !info->dynamic
+			   || h->dynamic
 			   || !h->def_regular))
 		outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
 	      else
--- binutils/bfd/elf64-x86-64.c.dynamic	2006-07-11 12:53:42.000000000 -0700
+++ binutils/bfd/elf64-x86-64.c	2006-07-24 13:42:14.000000000 -0700
@@ -998,6 +998,8 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		    && (r_type != R_X86_64_PC64))
 		   || (h != NULL
 		       && (! info->symbolic
+			   || ! info->dynamic
+			   || h->dynamic
 			   || h->root.type == bfd_link_hash_defweak
 			   || !h->def_regular))))
 	      || (ELIMINATE_COPY_RELOCS
@@ -2446,6 +2448,8 @@ elf64_x86_64_relocate_section (bfd *outp
 			   || r_type == R_X86_64_PC64
 			   || !info->shared
 			   || !info->symbolic
+			   || !info->dynamic
+			   || h->dynamic
 			   || !h->def_regular))
 		{
 		  outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
--- binutils/bfd/elflink.c.dynamic	2006-07-18 13:26:51.000000000 -0700
+++ binutils/bfd/elflink.c	2006-07-24 13:52:56.000000000 -0700
@@ -444,6 +444,21 @@ bfd_elf_link_record_dynamic_symbol (stru
   return TRUE;
 }
 \f
+/* Mark a symbol dynamic.  */
+
+void
+bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info,
+				  struct elf_link_hash_entry *h)
+{
+  struct bfd_elf_dynamic_list *d = info->dynamic;
+
+  if (d == NULL || info->relocatable)
+    return;
+
+  if ((*d->match) (&d->head, NULL, h->root.root.string))
+    h->dynamic = 1;
+}
+
 /* Record an assignment to a symbol made by a linker script.  We need
    this in case some dynamic object refers to this symbol.  */
 
@@ -477,7 +492,10 @@ bfd_elf_record_link_assignment (bfd *out
     }
 
   if (h->root.type == bfd_link_hash_new)
-    h->non_elf = 0;
+    {
+      bfd_elf_link_mark_dynamic_symbol (info, h);
+      h->non_elf = 0;
+    }
 
   /* If this symbol is being provided by the linker script, and it is
      currently defined by a dynamic object, but not by a regular
@@ -840,6 +858,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
 
   if (h->root.type == bfd_link_hash_new)
     {
+      bfd_elf_link_mark_dynamic_symbol (info, h);
       h->non_elf = 0;
       return TRUE;
     }
@@ -914,6 +933,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
   if (pold_alignment == NULL
       && !info->shared
       && !info->export_dynamic
+      && !h->dynamic
       && !h->ref_dynamic
       && newdyn
       && newdef
@@ -1626,6 +1646,10 @@ _bfd_elf_export_symbol (struct elf_link_
 {
   struct elf_info_failed *eif = data;
 
+  /* Ignore this if we won't export it.  */
+  if (!eif->info->export_dynamic && !h->dynamic)
+    return TRUE;
+
   /* Ignore indirect symbols.  These are added by the versioning code.  */
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
@@ -1842,6 +1866,7 @@ _bfd_elf_link_assign_sym_version (struct
 		  d = (*t->match) (&t->locals, NULL, alc);
 		  if (d != NULL
 		      && h->dynindx != -1
+		      && ! h->dynamic
 		      && ! info->export_dynamic)
 		    (*bed->elf_backend_hide_symbol) (info, h, TRUE);
 		}
@@ -1968,6 +1993,7 @@ _bfd_elf_link_assign_sym_version (struct
 	{
 	  h->verinfo.vertree = local_ver;
 	  if (h->dynindx != -1
+	      && ! h->dynamic
 	      && ! info->export_dynamic)
 	    {
 	      (*bed->elf_backend_hide_symbol) (info, h, TRUE);
@@ -2380,6 +2406,7 @@ _bfd_elf_fix_symbol_flags (struct elf_li
       && eif->info->shared
       && is_elf_hash_table (eif->info->hash)
       && (eif->info->symbolic
+	  || (eif->info->dynamic && !h->dynamic)
 	  || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
       && h->def_regular)
     {
@@ -2608,7 +2635,9 @@ _bfd_elf_dynamic_symbol_p (struct elf_li
 
   /* Identify the cases where name binding rules say that a
      visible symbol resolves locally.  */
-  binding_stays_local_p = info->executable || info->symbolic;
+  binding_stays_local_p = (info->executable
+			   || info->symbolic
+			   || (info->dynamic && !h->dynamic));
 
   switch (ELF_ST_VISIBILITY (h->other))
     {
@@ -2671,7 +2700,9 @@ _bfd_elf_symbol_refs_local_p (struct elf
   /* At this point, we know the symbol is defined and dynamic.  In an
      executable it must resolve locally, likewise when building symbolic
      shared libraries.  */
-  if (info->executable || info->symbolic)
+  if (info->executable
+      || info->symbolic 
+      || (info->dynamic && !h->dynamic))
     return TRUE;
 
   /* Now deal with defined dynamic symbols in shared libraries.  Ones
@@ -5306,7 +5337,7 @@ bfd_elf_size_dynamic_sections (bfd *outp
 
       /* If we are supposed to export all symbols into the dynamic symbol
 	 table (this is not the normal case), then do so.  */
-      if (info->export_dynamic)
+      if (info->export_dynamic || info->dynamic)
 	{
 	  elf_link_hash_traverse (elf_hash_table (info),
 				  _bfd_elf_export_symbol,
--- binutils/bfd/elfxx-ia64.c.dynamic	2006-06-20 11:59:14.000000000 -0700
+++ binutils/bfd/elfxx-ia64.c	2006-07-24 13:42:31.000000000 -0700
@@ -2742,6 +2742,8 @@ elfNN_ia64_check_relocs (abfd, info, sec
 	 this may help reduce memory usage and processing time later.  */
       maybe_dynamic = (h && ((!info->executable
 			      && (!info->symbolic
+				  || !info->dynamic
+				  || h->dynamic
 				  || info->unresolved_syms_in_shared_libs == RM_IGNORE))
 			     || !h->def_regular
 			     || h->root.type == bfd_link_hash_defweak));
@@ -2914,6 +2916,8 @@ elfNN_ia64_check_relocs (abfd, info, sec
 	 this may help reduce memory usage and processing time later.  */
       maybe_dynamic = (h && ((!info->executable
 			      && (!info->symbolic
+				  || !info->dynamic
+				  || h->dynamic
 				  || info->unresolved_syms_in_shared_libs == RM_IGNORE))
 			     || !h->def_regular
 			     || h->root.type == bfd_link_hash_defweak));
--- binutils/include/bfdlink.h.dynamic	2006-07-11 12:53:43.000000000 -0700
+++ binutils/include/bfdlink.h	2006-07-24 11:16:17.000000000 -0700
@@ -221,6 +221,8 @@ enum report_method
   RM_GENERATE_ERROR
 };
 
+struct bfd_elf_dynamic_list;
+
 /* This structure holds all the information needed to communicate
    between BFD and the linker when doing a link.  */
 
@@ -428,6 +430,9 @@ struct bfd_link_info
 
   /* Start and end of RELRO region.  */
   bfd_vma relro_start, relro_end;
+
+  /* List of symbols should be dynamic.  */
+  struct bfd_elf_dynamic_list *dynamic;
 };
 
 /* This structures holds a set of callback functions.  These are
@@ -721,4 +726,12 @@ struct bfd_elf_version_tree
      struct bfd_elf_version_expr *prev, const char *sym);
 };
 
+struct bfd_elf_dynamic_list
+{
+  struct bfd_elf_version_expr_head head;
+  struct bfd_elf_version_expr *(*match)
+    (struct bfd_elf_version_expr_head *head,
+     struct bfd_elf_version_expr *prev, const char *sym);
+};
+
 #endif
--- binutils/ld/ld.texinfo.dynamic	2006-07-11 12:53:43.000000000 -0700
+++ binutils/ld/ld.texinfo	2006-07-24 14:16:15.000000000 -0700
@@ -485,11 +485,11 @@ 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 in th executable or keep the dynamic
+relocation in the dynamic object.  See the description of
+@samp{--version-script} in @ref{VERSION}.
 
 @ifclear SingleFormat
 @cindex big-endian objects
@@ -1128,7 +1128,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 use the version
+script to control which symbols shouldn't 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
@@ -4464,6 +4467,24 @@ might change in the future, even if the 
 should check that all of your version directives are behaving as you
 expect when you upgrade.
 
+The nameless version node in the version script can be used to control
+which symbols should be exported in an executable or which symbols
+shouldn't be bound within a shared library.
+
+@smallexample
+@{ dynamic: foo; bar; @};
+@end smallexample
+
+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.  When a symbol in a shared library
+is listed as dynamic in a version script, its reference won't be bound
+to the definition within the shared library.  If a symbol isn't listed
+as dynamic, its reference will be bound to the definition within
+the shared library.  It is similar to @samp{-Bsymbolic}, except for
+that those symbols listed as dynamic won't be bound to their
+definitions.
+
 @node Expressions
 @section Expressions in Linker Scripts
 @cindex expressions
--- binutils/ld/ldgram.y.dynamic	2006-06-08 22:37:07.000000000 -0700
+++ binutils/ld/ldgram.y	2006-07-24 11:37:07.000000000 -0700
@@ -150,6 +150,7 @@ static int error_index;
 %token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
 %token <name> VERS_TAG VERS_IDENTIFIER
 %token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
+%token LD_DYNAMIC
 %token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL
 %token EXCLUDE_FILE
 %token CONSTANT
@@ -1217,6 +1218,10 @@ vers_tag:
 		{
 		  $$ = lang_new_vers_node ($3, $7);
 		}
+	|	LD_DYNAMIC ':' vers_defns ';'
+		{
+		  $$ = lang_new_dynamic_list ($3);
+		}
 	;
 
 vers_defns:
@@ -1283,6 +1288,14 @@ vers_defns:
 		{
 		  $$ = lang_new_vers_pattern ($1, "extern", ldgram_vers_current_lang, FALSE);
 		}
+	|	LD_DYNAMIC
+		{
+		  $$ = lang_new_vers_pattern (NULL, "dynamic", ldgram_vers_current_lang, FALSE);
+		}
+	|	vers_defns ';' LD_DYNAMIC
+		{
+		  $$ = lang_new_vers_pattern ($1, "dynamic", ldgram_vers_current_lang, FALSE);
+		}
 	;
 
 opt_semicolon:
--- binutils/ld/ldlang.c.dynamic	2006-07-18 13:26:51.000000000 -0700
+++ binutils/ld/ldlang.c	2006-07-24 14:49:20.000000000 -0700
@@ -6599,6 +6599,15 @@ lang_register_vers_node (const char *nam
   if (name == NULL)
     name = "";
 
+  if (version == NULL)
+    {
+      ASSERT (deps == NULL);
+      if (name[0] != '\0')
+	einfo (_("%F%P: Invalid version tag `%s'. Only anonymous "
+		 "version tag is allowed for dynamic list.\n"), name);
+      return;
+    }
+
   if ((name[0] == '\0' && lang_elf_version_info != NULL)
       || (lang_elf_version_info && lang_elf_version_info->name[0] == '\0'))
     {
@@ -6763,3 +6772,23 @@ lang_add_unique (const char *name)
   ent->next = unique_section_list;
   unique_section_list = ent;
 }
+
+/* Create a list of dynamic symbols.  */
+
+struct bfd_elf_version_tree *
+lang_new_dynamic_list (struct bfd_elf_version_expr *dynamic)
+{
+  struct bfd_elf_dynamic_list *d;
+
+  if (link_info.dynamic != NULL)
+    einfo (_("%F%P: Duplicated dynamic lists.\n"));
+
+  d = xcalloc (1, sizeof *d);
+  d->head.list = dynamic;
+  d->match = lang_vers_match;
+  link_info.dynamic = d;
+
+  lang_finalize_version_expr_head (&d->head);
+
+  return NULL;
+}
--- binutils/ld/ldlang.h.dynamic	2006-06-20 11:59:15.000000000 -0700
+++ binutils/ld/ldlang.h	2006-07-24 11:17:44.000000000 -0700
@@ -591,6 +591,8 @@ extern struct bfd_elf_version_deps *lang
   (struct bfd_elf_version_deps *, const char *);
 extern void lang_register_vers_node
   (const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
+extern struct bfd_elf_version_tree *lang_new_dynamic_list
+  (struct bfd_elf_version_expr *);
 bfd_boolean unique_section_p
   (const asection *);
 extern void lang_add_unique
--- binutils/ld/ldlex.l.dynamic	2006-05-30 09:45:42.000000000 -0700
+++ binutils/ld/ldlex.l	2006-07-23 15:30:01.000000000 -0700
@@ -405,6 +405,8 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([
 
 <VERS_NODE>local		{ RTOKEN(LOCAL); }
 
+<VERS_NODE>dynamic		{ RTOKEN(LD_DYNAMIC); }
+
 <VERS_NODE>extern		{ RTOKEN(EXTERN); }
 
 <VERS_NODE>{V_IDENTIFIER}	{ yylval.name = xstrdup (yytext);
--- binutils/ld/ldmain.c.dynamic	2006-07-11 12:53:43.000000000 -0700
+++ binutils/ld/ldmain.c	2006-07-24 11:22:55.000000000 -0700
@@ -318,6 +318,7 @@ main (int argc, char **argv)
   link_info.relax_pass = 1;
   link_info.warn_shared_textrel = FALSE;
   link_info.gc_sections = FALSE;
+  link_info.dynamic = NULL;
 
   config.maxpagesize = 0;
   config.commonpagesize = 0;

             reply	other threads:[~2006-07-24 22:27 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-07-24 22:27 H. J. Lu [this message]
2006-07-25 12:53 ` Ulrich Drepper
2006-07-25 13:49   ` H. J. Lu
2006-07-25 14:04     ` Ulrich Drepper
2006-07-25 14:36       ` H. J. Lu
2006-07-25 14:49         ` Ulrich Drepper
2006-07-26 16:42 ` Michael Matz
2006-07-27 17:11   ` H. J. Lu
2006-07-28 13:14     ` Michael Matz
2006-07-28 17:40       ` H. J. Lu
2006-07-28 17:59         ` Ulrich Drepper
2006-07-28 18:05           ` H. J. Lu
2006-08-08 17:22         ` H. J. Lu
2006-08-08 18:49           ` Michael Matz
2006-08-09 20:36             ` PATCH: Add --dynamic-list to ld H. J. Lu
2006-09-07 15:28               ` Nick Clifton
2006-09-07 19:41                 ` H. J. Lu
2006-09-08  8:17                   ` Nick Clifton
2006-10-10 15:50                 ` [PATCH] Fix --dynamic-list Jakub Jelinek
2006-10-11 15:39                   ` Nick Clifton
2006-10-16 22:45                     ` H. J. Lu
2006-10-18 18:19                       ` Nick Clifton
2006-08-09  2:02           ` RFC: Add dynamic list to version script Alan Modra
2006-08-09 16:05             ` Michael Matz
2006-08-09 16:19               ` Alan Modra
2006-08-09 17:40                 ` H. J. Lu
2006-08-09 16:25               ` H. J. Lu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060724221020.GA22024@lucon.org \
    --to=hjl@lucon.org \
    --cc=binutils@sources.redhat.com \
    --cc=matz@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).