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


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

Re: RFC: Add dynamic list to version script


On Fri, Jul 28, 2006 at 10:40:40AM -0700, H. J. Lu wrote:
> 
> I am thinking a special section containing a dynamic list and we can
> have a builtin dynamic list for C++. How about --dynamic-list and
> --dynamic-list-cpp?
> 
> 

This patch adds a new linker --dynamic-list option. You can have
as many --dynamic-list as you need. I can add a builtin option for
C++, something like --dynamic-list-cpp. I will add a few testcases if
this patch is accepted.


H.J.
----
bfd/

2006-08-08  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-08-08  H.J. Lu  <hongjiu.lu@intel.com>

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

ld/

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

	* NEWS: Mention --dynamic-list.

	* ld.texinfo: Document --dynamic-list.

	* ldgram.y: Support dynamic list.

	* ldlang.c (lang_process): Call lang_finalize_version_expr_head
	on link_info.dynamic if needed.
	(lang_append_dynamic_list): New.
	* ldlang.h (lang_append_dynamic_list): Likewise.

	* ldlex.h (input_enum): Add input_dynamic_list.
	* ldlex.l: Handle it.

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

	* lexsup.c (option_values): Add OPTION_DYNAMIC_LIST.
	(ld_options): Add an entry for OPTION_DYNAMIC_LIST.
	(parse_args): Handle OPTION_DYNAMIC_LIST.

--- binutils/bfd/elf-bfd.h.dynamic	2006-08-07 15:34:30.000000000 -0700
+++ binutils/bfd/elf-bfd.h	2006-08-07 15:34:30.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-08-07 15:34:30.000000000 -0700
@@ -1150,7 +1150,8 @@ elf_i386_check_relocs (bfd *abfd,
 	       && (sec->flags & SEC_ALLOC) != 0
 	       && (r_type != R_386_PC32
 		   || (h != NULL
-		       && (! info->symbolic
+		       && (! (info->symbolic
+			      || (info->dynamic && !h->dynamic))
 			   || h->root.type == bfd_link_hash_defweak
 			   || !h->def_regular))))
 	      || (ELIMINATE_COPY_RELOCS
@@ -2629,7 +2630,8 @@ elf_i386_relocate_section (bfd *output_b
 		       && h->dynindx != -1
 		       && (r_type == R_386_PC32
 			   || !info->shared
-			   || !info->symbolic
+			   || !(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-08-07 08:43:40.000000000 -0700
+++ binutils/bfd/elf64-x86-64.c	2006-08-07 15:34:30.000000000 -0700
@@ -997,7 +997,8 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		    && (r_type != R_X86_64_PC32)
 		    && (r_type != R_X86_64_PC64))
 		   || (h != NULL
-		       && (! info->symbolic
+		       && (! (info->symbolic
+			      || (info->dynamic && !h->dynamic))
 			   || h->root.type == bfd_link_hash_defweak
 			   || !h->def_regular))))
 	      || (ELIMINATE_COPY_RELOCS
@@ -2445,7 +2446,8 @@ elf64_x86_64_relocate_section (bfd *outp
 			   || r_type == R_X86_64_PC32
 			   || r_type == R_X86_64_PC64
 			   || !info->shared
-			   || !info->symbolic
+			   || !(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-08-07 15:34:30.000000000 -0700
+++ binutils/bfd/elflink.c	2006-08-07 15:34:30.000000000 -0700
@@ -444,6 +444,21 @@ bfd_elf_link_record_dynamic_symbol (stru
   return TRUE;
 }
 
+/* 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
@@ -5322,7 +5353,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-07-28 13:51:45.000000000 -0700
+++ binutils/bfd/elfxx-ia64.c	2006-08-07 15:34:30.000000000 -0700
@@ -2741,7 +2741,8 @@ elfNN_ia64_check_relocs (abfd, info, sec
 	 have yet been processed.  Do something with what we know, as
 	 this may help reduce memory usage and processing time later.  */
       maybe_dynamic = (h && ((!info->executable
-			      && (!info->symbolic
+			      && (!(info->symbolic
+				    || (info->dynamic && !h->dynamic))
 				  || info->unresolved_syms_in_shared_libs == RM_IGNORE))
 			     || !h->def_regular
 			     || h->root.type == bfd_link_hash_defweak));
@@ -2913,7 +2914,8 @@ elfNN_ia64_check_relocs (abfd, info, sec
 	 have yet been processed.  Do something with what we know, as
 	 this may help reduce memory usage and processing time later.  */
       maybe_dynamic = (h && ((!info->executable
-			      && (!info->symbolic
+			      && (!(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-08-07 08:43:40.000000000 -0700
+++ binutils/include/bfdlink.h	2006-08-07 15:34:30.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.  */
 
@@ -431,6 +433,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
@@ -724,4 +729,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/NEWS.dynamic	2006-08-07 08:43:40.000000000 -0700
+++ binutils/ld/NEWS	2006-08-08 09:49:22.000000000 -0700
@@ -1,4 +1,9 @@
 -*- text -*-
+* ELF: Add --dynamic-list option to specify a list of global symbols
+  whose references shouldn't be bound to the definition within the
+  shared library, or a list of symbols which should be added to the
+  symbol table in the executable. 
+
 * New switch: --print-gc-sections to list any sections removed by garabge
   collection.
 
--- binutils/ld/ld.texinfo.dynamic	2006-08-07 08:43:40.000000000 -0700
+++ binutils/ld/ld.texinfo	2006-08-08 09:47:22.000000000 -0700
@@ -487,9 +487,9 @@ back to the symbols defined by the progr
 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
+You can also use the dynamic list 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}.
+See the description of @samp{--dynamic-list}.
 
 @ifclear SingleFormat
 @cindex big-endian objects
@@ -1130,6 +1130,19 @@ for a program linked against a shared li
 within the shared library.  This option is only meaningful on ELF
 platforms which support shared libraries.
 
+@kindex --dynamic-list=@var{dynamic-list-file}
+@item --dynamic-list=@var{dynamic-list-file}
+Specify the name of a dynamic list file to the linker.  This is
+typically used when creating shared libraries to specify a list of
+global symbols whose references shouldn't be bound to the definition
+within the shared library, or creating dynamically linked executables
+to specify a list of symbols which should be added to the symbol table
+in the executable.  This option is only meaningful on ELF platforms
+which support shared libraries.
+
+The format of the dynamic list is the same as the version node without
+scope and node name.  See @ref{VERSION} for more information.
+
 @kindex --check-sections
 @kindex --no-check-sections
 @item --check-sections
--- binutils/ld/ldgram.y.dynamic	2006-06-08 22:37:07.000000000 -0700
+++ binutils/ld/ldgram.y	2006-08-08 08:58:33.000000000 -0700
@@ -156,6 +156,7 @@ static int error_index;
 %type <versyms> vers_defns
 %type <versnode> vers_tag
 %type <deflist> verdep
+%token INPUT_DYNAMIC_LIST
 
 %%
 
@@ -163,6 +164,7 @@ file:
 		INPUT_SCRIPT script_file
 	|	INPUT_MRI_SCRIPT mri_script_file
 	|	INPUT_VERSION_SCRIPT version_script_file
+	|	INPUT_DYNAMIC_LIST dynamic_list_file
 	|	INPUT_DEFSYM defsym_expr
 	;
 
@@ -1139,6 +1141,34 @@ phdr_val:
 		}
 	;
 
+dynamic_list_file:
+		{
+		  ldlex_version_file ();
+		  PUSH_ERROR (_("dynamic list"));
+		}
+		dynamic_list_nodes
+		{
+		  ldlex_popstate ();
+		  POP_ERROR ();
+		}
+	;
+
+dynamic_list_nodes:
+		dynamic_list_node
+	|	dynamic_list_nodes dynamic_list_node
+	;
+
+dynamic_list_node:
+		'{' dynamic_list_tag '}' ';'
+	;
+
+dynamic_list_tag:
+		vers_defns ';'
+		{
+		  lang_append_dynamic_list ($1);
+		}
+	;
+
 /* This syntax is used within an external version script file.  */
 
 version_script_file:
--- binutils/ld/ldlang.c.dynamic	2006-08-07 15:34:30.000000000 -0700
+++ binutils/ld/ldlang.c	2006-08-08 08:52:25.000000000 -0700
@@ -83,6 +83,8 @@ static void print_input_section (asectio
 static bfd_boolean lang_one_common (struct bfd_link_hash_entry *, void *);
 static void lang_record_phdrs (void);
 static void lang_do_version_exports_section (void);
+static void lang_finalize_version_expr_head
+  (struct bfd_elf_version_expr_head *);
 
 /* Exported variables.  */
 lang_output_section_statement_type *abs_output_section;
@@ -5583,6 +5585,10 @@ relax_sections (void)
 void
 lang_process (void)
 {
+  /* Finalize dynamic list.  */
+  if (link_info.dynamic)
+    lang_finalize_version_expr_head (&link_info.dynamic->head);
+
   current_target = default_target;
 
   /* Open the output file.  */
@@ -6885,3 +6891,24 @@ lang_add_unique (const char *name)
   ent->next = unique_section_list;
   unique_section_list = ent;
 }
+
+/* Append the list of dynamic symbols to the existing one.  */
+
+void
+lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
+{
+  if (link_info.dynamic)
+    {
+      dynamic->next = link_info.dynamic->head.list;
+      link_info.dynamic->head.list = dynamic;
+    }
+  else
+    {
+      struct bfd_elf_dynamic_list *d;
+
+      d = xcalloc (1, sizeof *d);
+      d->head.list = dynamic;
+      d->match = lang_vers_match;
+      link_info.dynamic = d;
+    }
+}
--- binutils/ld/ldlang.h.dynamic	2006-08-07 15:34:30.000000000 -0700
+++ binutils/ld/ldlang.h	2006-08-08 08:52:51.000000000 -0700
@@ -601,6 +601,7 @@ 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 void lang_append_dynamic_list (struct bfd_elf_version_expr *);
 bfd_boolean unique_section_p
   (const asection *);
 extern void lang_add_unique
--- binutils/ld/ldlex.h.dynamic	2005-05-16 11:04:40.000000000 -0700
+++ binutils/ld/ldlex.h	2006-08-07 18:44:47.000000000 -0700
@@ -30,6 +30,7 @@ typedef enum input_enum {
   input_script,
   input_mri_script,
   input_version_script,
+  input_dynamic_list,
   input_defsym
 } input_type;
 
--- binutils/ld/ldlex.l.dynamic	2006-05-30 09:45:42.000000000 -0700
+++ binutils/ld/ldlex.l	2006-08-07 19:25:59.000000000 -0700
@@ -132,6 +132,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([
 	case input_script: return INPUT_SCRIPT; break;
 	case input_mri_script: return INPUT_MRI_SCRIPT; break;
 	case input_version_script: return INPUT_VERSION_SCRIPT; break;
+	case input_dynamic_list: return INPUT_DYNAMIC_LIST; break;
 	case input_defsym: return INPUT_DEFSYM; break;
 	default: abort ();
 	}
--- binutils/ld/ldmain.c.dynamic	2006-08-07 08:43:40.000000000 -0700
+++ binutils/ld/ldmain.c	2006-08-07 15:34:31.000000000 -0700
@@ -319,6 +319,7 @@ main (int argc, char **argv)
   link_info.warn_shared_textrel = FALSE;
   link_info.gc_sections = FALSE;
   link_info.print_gc_sections = FALSE;
+  link_info.dynamic = NULL;
 
   config.maxpagesize = 0;
   config.commonpagesize = 0;
--- binutils/ld/lexsup.c.dynamic	2006-08-07 08:43:40.000000000 -0700
+++ binutils/ld/lexsup.c	2006-08-07 18:49:50.000000000 -0700
@@ -107,6 +107,7 @@ enum option_values
   OPTION_VERSION,
   OPTION_VERSION_SCRIPT,
   OPTION_VERSION_EXPORTS_SECTION,
+  OPTION_DYNAMIC_LIST,
   OPTION_WARN_COMMON,
   OPTION_WARN_CONSTRUCTORS,
   OPTION_WARN_FATAL,
@@ -501,6 +502,8 @@ static const struct ld_option ld_options
      OPTION_VERSION_EXPORTS_SECTION },
     '\0', N_("SYMBOL"), N_("Take export symbols list from .exports, using\n"
 			   "\t\t\t\tSYMBOL as the version."), TWO_DASHES },
+  { {"dynamic-list", required_argument, NULL, OPTION_DYNAMIC_LIST},
+    '\0', N_("FILE"), N_("Read dynamic list"), TWO_DASHES },
   { {"warn-common", no_argument, NULL, OPTION_WARN_COMMON},
     '\0', NULL, N_("Warn about duplicate common symbols"), TWO_DASHES },
   { {"warn-constructors", no_argument, NULL, OPTION_WARN_CONSTRUCTORS},
@@ -1236,6 +1239,20 @@ parse_args (unsigned argc, char **argv)
 	     .exports sections.  */
 	  command_line.version_exports_section = optarg;
 	  break;
+	case OPTION_DYNAMIC_LIST:
+	  /* This option indicates a small script that only specifies
+	     a dynamic list.  Read it, but don't assume that we've
+	     seen a linker script.  */
+	  {
+	    FILE *hold_script_handle;
+
+	    hold_script_handle = saved_script_handle;
+	    ldfile_open_command_file (optarg);
+	    saved_script_handle = hold_script_handle;
+	    parser_input = input_dynamic_list;
+	    yyparse ();
+	  }
+	  break;
 	case OPTION_WARN_COMMON:
 	  config.warn_common = TRUE;
 	  break;


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