bfd/
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 7 Sep 2006 17:16:34 +0000 (17:16 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 7 Sep 2006 17:16:34 +0000 (17:16 +0000)
2006-09-07  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-09-07  H.J. Lu  <hongjiu.lu@intel.com>

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

ld/

2006-09-07  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/

2006-09-07  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.

40 files changed:
bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf32-i386.c
bfd/elf64-x86-64.c
bfd/elflink.c
bfd/elfxx-ia64.c
include/ChangeLog
include/bfdlink.h
ld/ChangeLog
ld/Makefile.am
ld/Makefile.in
ld/NEWS
ld/ld.texinfo
ld/ldgram.y
ld/ldlang.c
ld/ldlang.h
ld/ldlex.h
ld/ldlex.l
ld/ldmain.c
ld/lexsup.c
ld/testsuite/ChangeLog
ld/testsuite/ld-elf/dl1.c [new file with mode: 0644]
ld/testsuite/ld-elf/dl1.list [new file with mode: 0644]
ld/testsuite/ld-elf/dl1.out [new file with mode: 0644]
ld/testsuite/ld-elf/dl1main.c [new file with mode: 0644]
ld/testsuite/ld-elf/dl2.c [new file with mode: 0644]
ld/testsuite/ld-elf/dl2.list [new file with mode: 0644]
ld/testsuite/ld-elf/dl2a.out [new file with mode: 0644]
ld/testsuite/ld-elf/dl2b.out [new file with mode: 0644]
ld/testsuite/ld-elf/dl2main.c [new file with mode: 0644]
ld/testsuite/ld-elf/dl2xxx.c [new file with mode: 0644]
ld/testsuite/ld-elf/dl2xxx.list [new file with mode: 0644]
ld/testsuite/ld-elf/dl3.cc [new file with mode: 0644]
ld/testsuite/ld-elf/dl3.list [new file with mode: 0644]
ld/testsuite/ld-elf/dl3a.out [new file with mode: 0644]
ld/testsuite/ld-elf/dl3b.out [new file with mode: 0644]
ld/testsuite/ld-elf/dl3header.h [new file with mode: 0644]
ld/testsuite/ld-elf/dl3main.cc [new file with mode: 0644]
ld/testsuite/ld-elf/shared.exp
ld/testsuite/lib/ld-lib.exp

index 5df36f34eee784c0a0190ae10f467d4a0e445c10..88cff5c8b83757e88a689c74d34294c00b5b9353 100644 (file)
@@ -1,3 +1,27 @@
+2006-09-07  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.
+
 2006-09-05  Bibo Mao  <bibo.mao@intel.com>
 
        PR binutils/3171
index e7d3b1888045aa1b5d085ae8a9d04d1f6c2054e5..32b381c8adad60e3a69567b2cbcb7ad0ea65b9e8 100644 (file)
@@ -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
@@ -1828,6 +1830,9 @@ extern bfd_boolean bfd_elf_link_record_dynamic_symbol
 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 *);
 
@@ -1980,4 +1985,9 @@ extern bfd_boolean _sh_elf_set_mach_from_flags
     }                                                                  \
   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_ */
index ab02b2cad2c9e9e666fbca930117da8ba203ba11..7fb142289ac161307de52fff6311360846e6ea70 100644 (file)
@@ -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_bfd,
                       && 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
index 34fde961e36afc17aed25177ddcc4afd26d6b2c1..d84b82ea39c486ed296933f22fe83547ddefd103 100644 (file)
@@ -997,7 +997,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
                    && (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 *output_bfd, struct bfd_link_info *info,
                           || 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);
index a7657f9f0025f24ddb7fc1c6fc95ca30427c9eb1..d3f9b62ca6074279bc909f929941fa5e769f87c0 100644 (file)
@@ -444,6 +444,21 @@ bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
   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 *output_bfd,
     }
 
   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_hash_entry *h, void *data)
 {
   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_link_hash_entry *h,
   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_link_hash_entry *h,
 
   /* 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_link_hash_entry *h,
   /* 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 *output_bfd,
 
       /* 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,
index 11bba4e883ce5fcb4c6754b97d8c608f0ab7d397..2af3fb452bd256e500c55a564bec70e0f7bdc898 100644 (file)
@@ -2741,7 +2741,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
         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, relocs)
         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));
index 5140f8d196471a77a64778f1390c6053fe632a8e..b072b52fc8b9f809d59ee8451d2d4721adc13171 100644 (file)
@@ -1,3 +1,8 @@
+2006-09-07  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * bfdlink.h (bfd_elf_dynamic_list): New.
+       (bfd_link_info): Add a dynamic field.
+
 2006-08-04  Marcelo Tosatti  <marcelo@kvack.org>
 
        * bfdlink.h (struct bfd_link_info): New field: print_gc_sections.
index bbedd6089f2d082a40f2bbd80883e2350add171a..0cc91775ae7541ba959315c2736dd0669c48c316 100644 (file)
@@ -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
index a81518a0f29df1c6c38cf7b72e71000e201ce512..1da5d7ff13118b75a241cac8f4bf48d5644e4ec7 100644 (file)
@@ -1,3 +1,34 @@
+2006-09-07  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.
+
 2006-09-07  Joel Sherrill <joel.sherrill@oarcorp.com>
 
        * emulparams/h8300elf.sh: _tinydata should not be placed in
index 29738a6727fd517d9c6cc94193e4a79940f64a17..3fad390b7e0a810d23eab64c2e0e3849bda2cdb5 100644 (file)
@@ -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`
 
index 63d019280bd62414e523fab10bf93bd360b6404e..53aed95ca34bfaa77be7e3b185e85383bb9e8964 100644 (file)
@@ -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`
 
diff --git a/ld/NEWS b/ld/NEWS
index 89d4cd5c4b7a5cdff24caee77e2728de70eddf0d..7856bf8a5e87c542f2bd70080a3dd8101845c152 100644 (file)
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -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.
+
 * The default output section LMA has changed for allocatable sections from
   being equal to VMA, to keeping the difference between LMA and VMA the same as
   the previous output section in the same region.  This is a more useful
index ea21283483d5f4f08afb3677900b74b71faca0cf..283ee082712c43345d7a65bc61938cf88c7293e8 100644 (file)
@@ -487,9 +487,9 @@ 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
+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 library to override the definition
 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
index 4eb974deb8636835dfce6a19a9627bc3f3495721..61ebf9eb4d5512a5e8c031eed9e29192204fdc46 100644 (file)
@@ -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:
index 5826557d420ad62479e8c42d97eb3da5276812d0..bd9fd89a528cd720c4aa6d0e50be8db47fd1f73f 100644 (file)
@@ -83,6 +83,8 @@ static void print_input_section (asection *);
 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;
@@ -5624,6 +5626,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.  */
@@ -6926,3 +6932,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);
+}
index 1c135b6b24708648599b982c98e1400f4f4e9e52..6106cea4f92e6d42a9682fbc5967f3835dfd893b 100644 (file)
@@ -602,6 +602,8 @@ extern struct bfd_elf_version_deps *lang_add_vers_depend
   (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
index d35ead6a648984670e99e47290eb7d5f37fff2db..f274c6826dfa433b4b74b9c3c6ec0769073618df 100644 (file)
@@ -30,6 +30,7 @@ typedef enum input_enum {
   input_script,
   input_mri_script,
   input_version_script,
+  input_dynamic_list,
   input_defsym
 } input_type;
 
index 10339dd1779f842d76334df965a4f34c47368b35..a0563151c879fe1020acd72e4c0e11e1434859ae 100644 (file)
@@ -132,6 +132,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
        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 ();
        }
index 4dab0d6bd4d601cf0e2f63d9567b6c9dc9ac97d5..d9b434323d0ba73028f509def364eda7fa6af04f 100644 (file)
@@ -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;
index 4d526b0b67387ff7384f4246132a8f68afabc181..19cb037f0db5af9b27851e708c4bfa870b6c056b 100644 (file)
@@ -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;
index 62c6fda37e7286b1d399bce564aab454dc1a05a8..7dfff2327068288075b1e17d2201d1449107adbe 100644 (file)
@@ -1,3 +1,30 @@
+2006-09-07  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.
+
 2006-08-29  Alan Modra  <amodra@bigpond.net.au>
 
        * ld-elf/loadaddr3a.d: Adjust target test.
diff --git a/ld/testsuite/ld-elf/dl1.c b/ld/testsuite/ld-elf/dl1.c
new file mode 100644 (file)
index 0000000..09426f3
--- /dev/null
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+extern int bar;
+
+void
+foo (void)
+{
+  if (bar == -20)
+    printf ("OK\n");
+}
diff --git a/ld/testsuite/ld-elf/dl1.list b/ld/testsuite/ld-elf/dl1.list
new file mode 100644 (file)
index 0000000..9ffada0
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  extern "C"
+    {
+      bar;
+    };
+};
diff --git a/ld/testsuite/ld-elf/dl1.out b/ld/testsuite/ld-elf/dl1.out
new file mode 100644 (file)
index 0000000..d86bac9
--- /dev/null
@@ -0,0 +1 @@
+OK
diff --git a/ld/testsuite/ld-elf/dl1main.c b/ld/testsuite/ld-elf/dl1main.c
new file mode 100644 (file)
index 0000000..f277bf5
--- /dev/null
@@ -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;
+}
diff --git a/ld/testsuite/ld-elf/dl2.c b/ld/testsuite/ld-elf/dl2.c
new file mode 100644 (file)
index 0000000..b5cd927
--- /dev/null
@@ -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 ();
+}
diff --git a/ld/testsuite/ld-elf/dl2.list b/ld/testsuite/ld-elf/dl2.list
new file mode 100644 (file)
index 0000000..e985dcf
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  foo;
+};
diff --git a/ld/testsuite/ld-elf/dl2a.out b/ld/testsuite/ld-elf/dl2a.out
new file mode 100644 (file)
index 0000000..f3d5b9f
--- /dev/null
@@ -0,0 +1,3 @@
+OK1
+DSO
+OK1
diff --git a/ld/testsuite/ld-elf/dl2b.out b/ld/testsuite/ld-elf/dl2b.out
new file mode 100644 (file)
index 0000000..f30cead
--- /dev/null
@@ -0,0 +1,3 @@
+OK1
+MAIN
+OK1
diff --git a/ld/testsuite/ld-elf/dl2main.c b/ld/testsuite/ld-elf/dl2main.c
new file mode 100644 (file)
index 0000000..ddf677f
--- /dev/null
@@ -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;
+}
diff --git a/ld/testsuite/ld-elf/dl2xxx.c b/ld/testsuite/ld-elf/dl2xxx.c
new file mode 100644 (file)
index 0000000..cf3a1d0
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+void
+xxx (void)
+{
+  printf ("DSO\n");
+}
diff --git a/ld/testsuite/ld-elf/dl2xxx.list b/ld/testsuite/ld-elf/dl2xxx.list
new file mode 100644 (file)
index 0000000..9388cda
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  xxx;
+};
diff --git a/ld/testsuite/ld-elf/dl3.cc b/ld/testsuite/ld-elf/dl3.cc
new file mode 100644 (file)
index 0000000..558e49f
--- /dev/null
@@ -0,0 +1,7 @@
+#include "dl3header.h"
+
+void
+f (void)
+{
+  throw (A (42));
+}
diff --git a/ld/testsuite/ld-elf/dl3.list b/ld/testsuite/ld-elf/dl3.list
new file mode 100644 (file)
index 0000000..0b347ea
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  extern "C++"
+  {
+    typeinfo*;
+  };
+};
diff --git a/ld/testsuite/ld-elf/dl3a.out b/ld/testsuite/ld-elf/dl3a.out
new file mode 100644 (file)
index 0000000..d86bac9
--- /dev/null
@@ -0,0 +1 @@
+OK
diff --git a/ld/testsuite/ld-elf/dl3b.out b/ld/testsuite/ld-elf/dl3b.out
new file mode 100644 (file)
index 0000000..8a15044
--- /dev/null
@@ -0,0 +1 @@
+BAD2
diff --git a/ld/testsuite/ld-elf/dl3header.h b/ld/testsuite/ld-elf/dl3header.h
new file mode 100644 (file)
index 0000000..66f7d46
--- /dev/null
@@ -0,0 +1,5 @@
+struct A
+{
+  int i;
+  A (int i): i(i) {}
+};
diff --git a/ld/testsuite/ld-elf/dl3main.cc b/ld/testsuite/ld-elf/dl3main.cc
new file mode 100644 (file)
index 0000000..977f9bb
--- /dev/null
@@ -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;
+}
index 9222358dab31480916c22624d4496a6efff112ab..3090551f781897cce7be406f3f7b144bf177eae0 100644 (file)
@@ -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
index 4b6942847422891117e38645b6847ad9e82f7156..566845fc8757c1d75886c67ab31a59ebe3210b64 100644 (file)
@@ -1246,14 +1246,15 @@ if ![string length [info proc prune_warnings]] {
 
 # 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_xfail ldtests } {
     global subdir
     global env
     global CC
+    global CXX
     global CFLAGS
     global errcnt
 
@@ -1276,6 +1278,7 @@ proc run_ld_link_exec_tests { targets_to_xfail ldtests } {
        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_xfail ldtests } {
            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_xfail ldtests } {
 
 # 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