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]

PATCH: Add --dynamic-list to ld


On Tue, Aug 08, 2006 at 07:29:26PM +0200, Michael Matz wrote:
> Hi,
> 
> On Tue, 8 Aug 2006, H. J. Lu wrote:
> 
> > 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.
> 
> FWIW I like this :)
> 

Here is the updated patch. I added a few testcases. I added
--dynamic-list-cpp-typeinfo. I am not sure how useful it is since
in many cases, you want to add more than just RTTI in a C++ DSO.
--dynamic-list-cpp will be kind of misleading.



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.
	(SYMBOLIC_BIND): New.

	* elf32-i386.c (elf_i386_check_relocs): Replace info->symbolic
	with SYMBOLIC_BIND (info, h).
	(elf_i386_relocate_section): Likewise.
	* elf64-x86-64.c (elf64_x86_64_check_relocs): Likewise.
	(elf64_x86_64_relocate_section): 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_fix_symbol_flags): Replace info->symbolic with
	SYMBOLIC_BIND (info, h).
	(_bfd_elf_dynamic_symbol_p): Likewise.
	(_bfd_elf_symbol_refs_local_p): Likewise.
	(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>

	* Makefile.am (CXX): Set to g++.
	(CXX_FOR_TARGET): Likewise.
	* Makefile.in: Regenerated.

	* 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.
	(lang_append_dynamic_list_cpp_typeinfo): New.
	* ldlang.h (lang_append_dynamic_list): Likewise.
	* ldlang.h (lang_append_dynamic_list_cpp_typeinfo): 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 and
	OPTION_DYNAMIC_LIST_CPP_TYPEINFO.
	(ld_options): Add entries for OPTION_DYNAMIC_LIST and
	OPTION_DYNAMIC_LIST_CPP_TYPEINFO.
	(parse_args): Handle OPTION_DYNAMIC_LIST and
	OPTION_DYNAMIC_LIST_CPP_TYPEINFO.

ld/testsuite/ld-elf/

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

	* ld-elf/dl1.c: New file.
	* ld-elf/dl1.list: Likewise.
	* ld-elf/dl1.out: Likewise.
	* ld-elf/dl1main.c: Likewise.
	* ld-elf/dl2.c: Likewise.
	* ld-elf/dl2.list: Likewise.
	* ld-elf/dl2a.out: Likewise.
	* ld-elf/dl2b.out: Likewise.
	* ld-elf/dl2main.c: Likewise.
	* ld-elf/dl2xxx.c: Likewise.
	* ld-elf/dl2xxx.list: Likewise.
	* ld-elf/dl3.cc: Likewise.
	* ld-elf/dl3.list: Likewise.
	* ld-elf/dl3a.out: Likewise.
	* ld-elf/dl3b.out: Likewise.
	* ld-elf/dl3header.h: Likewise.
	* ld-elf/dl3main.cc: Likewise.

	* ld-elf/shared.exp: Updated.

	* lib/ld-lib.exp (run_ld_link_exec_tests): Take an optional
	argument for source language. Use CC/CXX for link, depending
	on source language.
	(run_cc_link_tests): Likewise.

--- binutils/bfd/elf-bfd.h.dynamic	2006-08-08 12:44:47.000000000 -0700
+++ binutils/bfd/elf-bfd.h	2006-08-09 11:21:04.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 *);
 
@@ -1985,4 +1990,9 @@ extern bfd_boolean _sh_elf_set_mach_from
     }									\
   while (0)
 
+/* Will a symbol be bound to the the definition within the shared
+   library, if any.  */
+#define SYMBOLIC_BIND(INFO, H) \
+    ((INFO)->symbolic || ((INFO)->dynamic && !(H)->dynamic))
+
 #endif /* _LIBELF_H_ */
--- binutils/bfd/elf32-i386.c.dynamic	2006-07-11 12:53:42.000000000 -0700
+++ binutils/bfd/elf32-i386.c	2006-08-09 11:22:03.000000000 -0700
@@ -1150,7 +1150,7 @@ elf_i386_check_relocs (bfd *abfd,
 	       && (sec->flags & SEC_ALLOC) != 0
 	       && (r_type != R_386_PC32
 		   || (h != NULL
-		       && (! info->symbolic
+		       && (! SYMBOLIC_BIND (info, h)
 			   || h->root.type == bfd_link_hash_defweak
 			   || !h->def_regular))))
 	      || (ELIMINATE_COPY_RELOCS
@@ -2629,7 +2629,7 @@ elf_i386_relocate_section (bfd *output_b
 		       && h->dynindx != -1
 		       && (r_type == R_386_PC32
 			   || !info->shared
-			   || !info->symbolic
+			   || !SYMBOLIC_BIND (info, h)
 			   || !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-09 11:23:39.000000000 -0700
@@ -997,7 +997,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		    && (r_type != R_X86_64_PC32)
 		    && (r_type != R_X86_64_PC64))
 		   || (h != NULL
-		       && (! info->symbolic
+		       && (! SYMBOLIC_BIND (info, h)
 			   || h->root.type == bfd_link_hash_defweak
 			   || !h->def_regular))))
 	      || (ELIMINATE_COPY_RELOCS
@@ -2445,7 +2445,7 @@ elf64_x86_64_relocate_section (bfd *outp
 			   || r_type == R_X86_64_PC32
 			   || r_type == R_X86_64_PC64
 			   || !info->shared
-			   || !info->symbolic
+			   || !SYMBOLIC_BIND (info, h)
 			   || !h->def_regular))
 		{
 		  outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
--- binutils/bfd/elflink.c.dynamic	2006-08-08 12:44:47.000000000 -0700
+++ binutils/bfd/elflink.c	2006-08-09 11:30:41.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;
     }
@@ -1626,6 +1645,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;
@@ -2379,7 +2402,7 @@ _bfd_elf_fix_symbol_flags (struct elf_li
   if (h->needs_plt
       && eif->info->shared
       && is_elf_hash_table (eif->info->hash)
-      && (eif->info->symbolic
+      && (SYMBOLIC_BIND (eif->info, h)
 	  || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
       && h->def_regular)
     {
@@ -2608,7 +2631,7 @@ _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 || SYMBOLIC_BIND (info, h);
 
   switch (ELF_ST_VISIBILITY (h->other))
     {
@@ -2671,7 +2694,7 @@ _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 || SYMBOLIC_BIND (info, h))
     return TRUE;
 
   /* Now deal with defined dynamic symbols in shared libraries.  Ones
@@ -5322,7 +5345,8 @@ 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->executable && 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-09 11:23:10.000000000 -0700
@@ -2741,7 +2741,7 @@ 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
+			      && (!SYMBOLIC_BIND (info, h)
 				  || info->unresolved_syms_in_shared_libs == RM_IGNORE))
 			     || !h->def_regular
 			     || h->root.type == bfd_link_hash_defweak));
@@ -2913,7 +2913,7 @@ 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
+			      && (!SYMBOLIC_BIND (info, h)
 				  || 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-08 12:44:48.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/Makefile.am.dynamic	2006-08-07 08:43:40.000000000 -0700
+++ binutils/ld/Makefile.am	2006-08-09 10:47:10.000000000 -0700
@@ -73,19 +73,19 @@ CC_FOR_TARGET = ` \
     fi; \
   fi`
 
-CXX = gcc
+CXX = g++
 CXX_FOR_TARGET = ` \
-  if [ -f $$r/../gcc/xgcc ] ; then \
+  if [ -f $$r/../gcc/g++ ] ; then \
     if [ -f $$r/../newlib/Makefile ] ; then \
-      echo $$r/../gcc/xgcc -B$$r/../gcc/ -idirafter $$r/../newlib/targ-include -idirafter $${srcroot}/../newlib/libc/include -nostdinc; \
+      echo $$r/../gcc/g++ -B$$r/../gcc/ -idirafter $$r/../newlib/targ-include -idirafter $${srcroot}/../newlib/libc/include -nostdinc; \
     else \
-      echo $$r/../gcc/xgcc -B$$r/../gcc/; \
+      echo $$r/../gcc/g++ -B$$r/../gcc/; \
     fi; \
   else \
     if [ "@host@" = "@target@" ] ; then \
       echo $(CXX); \
     else \
-      echo gcc | sed '$(transform)'; \
+      echo g++ | sed '$(transform)'; \
     fi; \
   fi`
 
--- binutils/ld/Makefile.in.dynamic	2006-08-07 08:43:40.000000000 -0700
+++ binutils/ld/Makefile.in	2006-08-09 10:51:07.000000000 -0700
@@ -302,19 +302,19 @@ CC_FOR_TARGET = ` \
     fi; \
   fi`
 
-CXX = gcc
+CXX = g++
 CXX_FOR_TARGET = ` \
-  if [ -f $$r/../gcc/xgcc ] ; then \
+  if [ -f $$r/../gcc/g++ ] ; then \
     if [ -f $$r/../newlib/Makefile ] ; then \
-      echo $$r/../gcc/xgcc -B$$r/../gcc/ -idirafter $$r/../newlib/targ-include -idirafter $${srcroot}/../newlib/libc/include -nostdinc; \
+      echo $$r/../gcc/g++ -B$$r/../gcc/ -idirafter $$r/../newlib/targ-include -idirafter $${srcroot}/../newlib/libc/include -nostdinc; \
     else \
-      echo $$r/../gcc/xgcc -B$$r/../gcc/; \
+      echo $$r/../gcc/g++ -B$$r/../gcc/; \
     fi; \
   else \
     if [ "@host@" = "@target@" ] ; then \
       echo $(CXX); \
     else \
-      echo gcc | sed '$(transform)'; \
+      echo g++ | sed '$(transform)'; \
     fi; \
   fi`
 
--- binutils/ld/NEWS.dynamic	2006-08-07 08:43:40.000000000 -0700
+++ binutils/ld/NEWS	2006-08-08 12:44:48.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 12:44:48.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 12:44:48.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-08 12:44:47.000000000 -0700
+++ binutils/ld/ldlang.c	2006-08-09 09:47:45.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,45 @@ 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;
+    }
+}
+
+/* Append the list of C++ typeinfo dynamic symbols to the existing
+   one.  */
+
+void
+lang_append_dynamic_list_cpp_typeinfo (void)
+{
+  const char * symbols [] =
+    {
+      "typeinfo name for*",
+      "typeinfo for*"
+    };
+  struct bfd_elf_version_expr *dynamic = NULL;
+  unsigned int i;
+
+  for (i = 0; i < ARRAY_SIZE (symbols); i++)
+    dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
+				     FALSE);
+
+  lang_append_dynamic_list (dynamic);
+}
--- binutils/ld/ldlang.h.dynamic	2006-08-08 12:43:37.000000000 -0700
+++ binutils/ld/ldlang.h	2006-08-09 09:46:50.000000000 -0700
@@ -601,6 +601,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 void lang_append_dynamic_list (struct bfd_elf_version_expr *);
+extern void lang_append_dynamic_list_cpp_typeinfo (void);
 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-08 12:44:48.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-08 12:44:48.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-08 12:44:48.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-09 09:46:37.000000000 -0700
@@ -107,6 +107,8 @@ enum option_values
   OPTION_VERSION,
   OPTION_VERSION_SCRIPT,
   OPTION_VERSION_EXPORTS_SECTION,
+  OPTION_DYNAMIC_LIST,
+  OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
   OPTION_WARN_COMMON,
   OPTION_WARN_CONSTRUCTORS,
   OPTION_WARN_FATAL,
@@ -501,6 +503,10 @@ 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-cpp-typeinfo", no_argument, NULL, OPTION_DYNAMIC_LIST_CPP_TYPEINFO},
+    '\0', NULL, N_("Use C++ typeinfo dynamic list"), 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 +1242,23 @@ parse_args (unsigned argc, char **argv)
 	     .exports sections.  */
 	  command_line.version_exports_section = optarg;
 	  break;
+	case OPTION_DYNAMIC_LIST_CPP_TYPEINFO:
+	  lang_append_dynamic_list_cpp_typeinfo ();
+	  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;
--- binutils/ld/testsuite/ld-elf/dl1.c.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl1.c	2006-08-08 15:38:50.000000000 -0700
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+extern int bar;
+
+void
+foo (void)
+{
+  if (bar == -20)
+    printf ("OK\n");
+}
--- binutils/ld/testsuite/ld-elf/dl1.list.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl1.list	2006-08-08 15:44:27.000000000 -0700
@@ -0,0 +1,6 @@
+{
+  extern "C"
+    {
+      bar;
+    };
+};
--- binutils/ld/testsuite/ld-elf/dl1.out.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl1.out	2006-08-08 15:38:27.000000000 -0700
@@ -0,0 +1 @@
+OK
--- binutils/ld/testsuite/ld-elf/dl1main.c.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl1main.c	2006-08-08 15:42:32.000000000 -0700
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <dlfcn.h>
+
+int bar = -20;
+
+int 
+main (void)
+{
+  int ret = 0;
+  void *handle;
+  void (*fcn) (void);
+
+  handle = dlopen("./tmpdir/libdl1.so", RTLD_GLOBAL|RTLD_LAZY);
+  if (!handle)
+    {
+      printf("dlopen libfoo.so: %s\n", dlerror ());
+      return 1;
+    }
+
+  fcn = (void (*)(void)) dlsym(handle, "foo");
+  if (!fcn)
+    {
+      printf("dlsym foo: %s\n", dlerror ());
+      ret += 1;
+    }
+  else
+    {
+      (*fcn) ();
+    }
+
+  dlclose (handle);
+  return ret;
+}
--- binutils/ld/testsuite/ld-elf/dl2.c.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl2.c	2006-08-08 16:03:10.000000000 -0700
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+int foo;
+
+extern void xxx (void);
+
+void
+bar (int x)
+{
+  if (foo == 1)
+    printf ("OK1\n");
+  else if (foo == 0)
+    printf ("OK2\n");
+  foo = -1;
+  xxx ();
+}
--- binutils/ld/testsuite/ld-elf/dl2.list.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl2.list	2006-08-08 15:58:54.000000000 -0700
@@ -0,0 +1,3 @@
+{
+  foo;
+};
--- binutils/ld/testsuite/ld-elf/dl2a.out.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl2a.out	2006-08-08 16:04:54.000000000 -0700
@@ -0,0 +1,3 @@
+OK1
+DSO
+OK1
--- binutils/ld/testsuite/ld-elf/dl2b.out.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl2b.out	2006-08-08 16:07:07.000000000 -0700
@@ -0,0 +1,3 @@
+OK1
+MAIN
+OK1
--- binutils/ld/testsuite/ld-elf/dl2main.c.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl2main.c	2006-08-08 16:03:15.000000000 -0700
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+extern int foo;
+extern void bar (void);
+
+void
+xxx (void)
+{
+  printf ("MAIN\n");
+}
+
+int
+main (void)
+{
+  foo = 1;
+  bar ();
+  if (foo == -1)
+    printf ("OK1\n");
+  else if (foo == 1)
+    printf ("OK2\n");
+  return 0;
+}
--- binutils/ld/testsuite/ld-elf/dl2xxx.c.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl2xxx.c	2006-08-08 16:03:23.000000000 -0700
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+void
+xxx (void)
+{
+  printf ("DSO\n");
+}
--- binutils/ld/testsuite/ld-elf/dl2xxx.list.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl2xxx.list	2006-08-08 16:05:30.000000000 -0700
@@ -0,0 +1,3 @@
+{
+  xxx;
+};
--- binutils/ld/testsuite/ld-elf/dl3.cc.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl3.cc	2006-08-08 16:17:42.000000000 -0700
@@ -0,0 +1,7 @@
+#include "dl3header.h"
+
+void
+f (void)
+{
+  throw (A (42));
+}
--- binutils/ld/testsuite/ld-elf/dl3.list.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl3.list	2006-08-08 16:16:12.000000000 -0700
@@ -0,0 +1,6 @@
+{
+  extern "C++"
+  {
+    typeinfo*;
+  };
+};
--- binutils/ld/testsuite/ld-elf/dl3a.out.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl3a.out	2006-08-09 11:05:44.000000000 -0700
@@ -0,0 +1 @@
+OK
--- binutils/ld/testsuite/ld-elf/dl3b.out.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl3b.out	2006-08-09 11:06:03.000000000 -0700
@@ -0,0 +1 @@
+BAD2
--- binutils/ld/testsuite/ld-elf/dl3header.h.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl3header.h	2006-08-08 16:11:48.000000000 -0700
@@ -0,0 +1,5 @@
+struct A
+{
+  int i;
+  A (int i): i(i) {}
+};
--- binutils/ld/testsuite/ld-elf/dl3main.cc.dynamic	2006-08-09 12:11:22.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/dl3main.cc	2006-08-08 16:18:56.000000000 -0700
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include "dl3header.h"
+
+extern void f (void);
+
+int
+main (void)
+{
+  try
+    {
+      f();
+    }
+  catch (A a)
+    {
+      if (a.i == 42)
+	printf ("OK\n");
+      else
+	printf ("BAD1\n");
+    }
+  catch (...)
+    {
+      printf ("BAD2\n");
+    }
+  return 0;
+}
--- binutils/ld/testsuite/ld-elf/shared.exp.dynamic	2006-07-12 08:45:33.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/shared.exp	2006-08-09 12:05:34.000000000 -0700
@@ -38,7 +38,7 @@ set build_tests {
    {foo.c} {} "libfoo.so"}
   {"Build versioned libfoo.so"
    "-shared -Wl,--version-script=foo.map" "-fPIC"
-   {foo.c} {} "libfoov.so" "-fPIC"}
+   {foo.c} {} "libfoov.so"}
   {"Build libbar.so"
    "-shared" "-fPIC"
    {begin.c end.c} {} "libbar.so"}
@@ -66,6 +66,15 @@ set build_tests {
   {"Build protected libbar.so with versioned libfoo.so"
    "-shared tmpdir/begin.o tmpdir/libfoov.so" "-fPIC"
    {endprotected.c} {} "libbarpfoov.so"}
+  {"Build libdl1.so"
+   "-shared" "-fPIC"
+   {dl1.c} {} "libdl1.so"}
+  {"Build libdl2a.so with --dynamic-list=dl2.list"
+   "-shared -Wl,--dynamic-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2a.so"}
+  {"Build libdl2b.so with --dynamic-list=dl2.list and dl2xxx.list"
+   "-shared -Wl,--dynamic-list=dl2.list,--dynamic-list=dl2xxx.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2b.so"}
 }
 
 set run_tests {
@@ -105,8 +114,49 @@ set run_tests {
     {"Run hidden libbar.so with versioned libfoo.so"
      "tmpdir/libbarhfoov.so tmpdir/libfoov.so" ""
      {main.c} "hidden" "hidden.out"}
+    {"Run with dlopen on libdl1.so"
+     "--dynamic-list=dl1.list -ldl" ""
+     {dl1main.c} "dl1" "dl1.out"}
+    {"Run with libdl2a.so"
+     "tmpdir/libdl2a.so" ""
+     {dl2main.c} "dl2a" "dl2a.out"}
+    {"Run with libdl2b.so"
+     "tmpdir/libdl2b.so" ""
+     {dl2main.c} "dl2b" "dl2b.out"}
 }
 
 run_cc_link_tests $build_tests
 # NetBSD ELF systems do not currently support the .*_array sections.
 run_ld_link_exec_tests [list "*-*-netbsdelf*"] $run_tests
+
+# Check if compiler works
+if { [which $CXX] == 0 } {
+    return
+}
+
+set build_cxx_tests {
+  {"Build libdl3a.so with --dynamic-list=dl3.list"
+   "-shared -Wl,--dynamic-list=dl3.list" "-fPIC"
+   {dl3.cc} {} "libdl3a.so" "c++"}
+  {"Build libdl3b.so with -Bsymbolic"
+   "-shared -Wl,-Bsymbolic" "-fPIC"
+   {dl3.cc} {} "libdl3b.so" "c++"}
+  {"Build libdl3a.so with --dynamic-list-cpp-typeinfo"
+   "-shared -Wl,--dynamic-list-cpp-typeinfo" "-fPIC"
+   {dl3.cc} {} "libdl3c.so" "c++"}
+}
+
+set run_cxx_tests {
+    {"Run with libdl3a.so"
+     "tmpdir/libdl3a.so" ""
+     {dl3main.cc} "dl3a" "dl3a.out" "" "c++"}
+    {"Run with libdl3b.so"
+     "tmpdir/libdl3b.so" ""
+     {dl3main.cc} "dl3b" "dl3b.out" "" "c++"}
+    {"Run with libdl3c.so"
+     "tmpdir/libdl3c.so" ""
+     {dl3main.cc} "dl3c" "dl3a.out" "" "c++"}
+}
+
+run_cc_link_tests $build_cxx_tests
+run_ld_link_exec_tests [] $run_cxx_tests
--- binutils/ld/testsuite/lib/ld-lib.exp.dynamic	2006-07-12 08:46:01.000000000 -0700
+++ binutils/ld/testsuite/lib/ld-lib.exp	2006-08-09 11:04:52.000000000 -0700
@@ -1246,14 +1246,15 @@ if ![string length [info proc prune_warn
 
 # targets_to_xfail is a list of target triplets to be xfailed.
 # ldtests contains test-items with 3 items followed by 1 lists, 2 items
-# and one optional item:
+# and 2 optional items:
 #   0:name
 #   1:ld options
 #   2:assembler options
-#   3:filenames of assembler files
+#   3:filenames of source files
 #   4:name of output file
 #   5:expected output
 #   6:compiler flags (optional)
+#   7:language (optional)
 
 proc run_ld_link_exec_tests { targets_to_xfail ldtests } {
     global ld
@@ -1262,6 +1263,7 @@ proc run_ld_link_exec_tests { targets_to
     global subdir
     global env
     global CC
+    global CXX
     global CFLAGS
     global errcnt
 
@@ -1276,6 +1278,7 @@ proc run_ld_link_exec_tests { targets_to
 	set binfile tmpdir/[lindex $testitem 4]
 	set expfile [lindex $testitem 5]
 	set cflags [lindex $testitem 6]
+	set lang [lindex $testitem 7]
 	set objfiles {}
 	set failed 0
 
@@ -1297,7 +1300,13 @@ proc run_ld_link_exec_tests { targets_to
 	    ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
 
 	    # We have to use $CC to build PIE and shared library.
-	    if { [ string match "-shared" $ld_options ] \
+	    if { [ string match "c" $lang ] } {
+		set link_proc ld_simple_link
+		set link_cmd $CC
+	    } elseif { [ string match "c++" $lang ] } {
+		set link_proc ld_simple_link
+		set link_cmd $CXX
+	    } elseif { [ string match "-shared" $ld_options ] \
 		 || [ string match "-pie" $ld_options ] } {
 		set link_proc ld_simple_link
 		set link_cmd $CC
@@ -1344,8 +1353,13 @@ proc run_ld_link_exec_tests { targets_to
 
 # List contains test-items with 3 items followed by 2 lists, one item and
 # one optional item:
-# 0:name 1:link options 2:compile options
-# 3:filenames of assembler files 4: action and options. 5: name of output file
+#  0:name
+#  1:link options
+#  2:compile options
+#  3:filenames of source files
+#  4:action and options.
+#  5:name of output file
+#  6:language (optional)
 #
 # Actions:
 # objdump: Apply objdump options on result.  Compare with regex (last arg).
@@ -1360,6 +1374,7 @@ proc run_cc_link_tests { ldtests } {
     global subdir
     global env
     global CC
+    global CXX
     global CFLAGS
 
     foreach testitem $ldtests {
@@ -1369,6 +1384,7 @@ proc run_cc_link_tests { ldtests } {
 	set src_files  [lindex $testitem 3]
 	set actions [lindex $testitem 4]
 	set binfile tmpdir/[lindex $testitem 5]
+	set lang [lindex $testitem 6]
 	set objfiles {}
 	set is_unresolved 0
 	set failed 0
@@ -1387,7 +1403,13 @@ proc run_cc_link_tests { ldtests } {
 	# Clear error and warning counts.
 	reset_vars
 
-	if ![ld_simple_link $CC $binfile "-L$srcdir/$subdir $ldflags $objfiles"] {
+	if { [ string match "c++" $lang ] } {
+	    set cc_cmd $CXX
+	} else {
+	    set cc_cmd $CC
+	}
+
+	if ![ld_simple_link $cc_cmd $binfile "-L$srcdir/$subdir $ldflags $objfiles"] {
 	    fail $testname
 	} else {
 	    set failed 0


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