On Tue, Jan 09, 2007 at 07:52:42AM -0800, H. J. Lu wrote: > > > > What about just --dynamic-list-cpp that enables the new behavior and > > implies --dynamic-list-cpp-typeinfo (I know that it is useless in this > > particular case, since C++ typeinfo is data, but in general such an > > option sounds more useful than only --dynamic-list-cpp-new). > > I think you only need --dynamic-list-cpp-new for building libstdc++.so. > -Bsymbolic-functions should be sufficient for other C++ shared > libraries. >
Here is a patch for --dynamic-list-cpp-new with a testcase. H.J. --- ld/ 2007-01-09 H.J. Lu <[EMAIL PROTECTED]> * NEWS: Mention --dynamic-list-cpp-new. * ld.texinfo: Document --dynamic-list-cpp-new. * ldlang.c (lang_append_dynamic_list_cpp_new): New. * ldlang.h (lang_append_dynamic_list_cpp_new): Likewise. * lexsup.c (option_values): Add OPTION_DYNAMIC_LIST_CPP_NEW. (ld_options): Add entry for --dynamic-list-cpp-new. (parse_args): Handle OPTION_DYNAMIC_LIST_CPP_NEW. ld/testsuite/ 2007-01-09 H.J. Lu <[EMAIL PROTECTED]> * ld-elf/del.cc: New. * ld-elf/dl5.cc: Likewise. * ld-elf/dl5.out: Likewise. * ld-elf/new.cc: Likewise. * ld-elf/shared.exp: Add --dynamic-list-cpp-new testcase. --- ld/NEWS.new 2007-01-09 11:34:46.000000000 -0800 +++ ld/NEWS 2007-01-09 11:34:53.000000000 -0800 @@ -1,4 +1,7 @@ -*- text -*- +* ELF: Add --dynamic-list-cpp-new, which puts C++ operator new and + delete on the dynamic list. + * ELF: Add -Bsymbolic-functions and --dynamic-list-data, builtin list for --dynamic-list, which puts global data symbols on the dynamic list. --- ld/ld.texinfo.new 2007-01-09 11:22:59.000000000 -0800 +++ ld/ld.texinfo 2007-01-09 11:31:50.000000000 -0800 @@ -1155,6 +1155,11 @@ scope and node name. See @ref{VERSION} @item --dynamic-list-data Include all global data symbols to the dynamic list. [EMAIL PROTECTED] --dynamic-list-cpp-new [EMAIL PROTECTED] --dynamic-list-cpp-new +Provide the builtin dynamic list for C++ operator new and delete. It +is mainly useful for building shared libstdc++. + @kindex --dynamic-list-cpp-typeinfo @item --dynamic-list-cpp-typeinfo Provide the builtin dynamic list for C++ runtime type identification. --- ld/ldlang.c.new 2007-01-09 11:22:59.000000000 -0800 +++ ld/ldlang.c 2007-01-09 11:22:59.000000000 -0800 @@ -7086,3 +7086,24 @@ lang_append_dynamic_list_cpp_typeinfo (v lang_append_dynamic_list (dynamic); } + +/* Append the list of C++ operator new and delete dynamic symbols to the + existing one. */ + +void +lang_append_dynamic_list_cpp_new (void) +{ + const char * symbols [] = + { + "operator new*", + "operator delete*" + }; + 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); +} --- ld/ldlang.h.new 2006-10-24 23:49:21.000000000 -0700 +++ ld/ldlang.h 2007-01-09 11:22:59.000000000 -0800 @@ -607,6 +607,7 @@ 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); +extern void lang_append_dynamic_list_cpp_new (void); bfd_boolean unique_section_p (const asection *); extern void lang_add_unique --- ld/lexsup.c.new 2007-01-09 11:22:59.000000000 -0800 +++ ld/lexsup.c 2007-01-09 11:24:13.000000000 -0800 @@ -108,6 +108,7 @@ enum option_values OPTION_VERSION_SCRIPT, OPTION_VERSION_EXPORTS_SECTION, OPTION_DYNAMIC_LIST, + OPTION_DYNAMIC_LIST_CPP_NEW, OPTION_DYNAMIC_LIST_CPP_TYPEINFO, OPTION_DYNAMIC_LIST_DATA, OPTION_WARN_COMMON, @@ -508,6 +509,8 @@ static const struct ld_option ld_options '\0', NULL, N_("Bind global function references locally"), ONE_DASH }, { {"dynamic-list-data", no_argument, NULL, OPTION_DYNAMIC_LIST_DATA}, '\0', NULL, N_("Add data symbols to dynamic list"), TWO_DASHES }, + { {"dynamic-list-cpp-new", no_argument, NULL, OPTION_DYNAMIC_LIST_CPP_NEW}, + '\0', NULL, N_("Use C++ operator new/delete dynamic list"), 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}, @@ -1257,6 +1260,10 @@ parse_args (unsigned argc, char **argv) lang_append_dynamic_list_cpp_typeinfo (); link_info.dynamic = TRUE; break; + case OPTION_DYNAMIC_LIST_CPP_NEW: + lang_append_dynamic_list_cpp_new (); + link_info.dynamic = TRUE; + 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 --- ld/testsuite/ld-elf/del.cc.new 2007-01-09 14:48:18.000000000 -0800 +++ ld/testsuite/ld-elf/del.cc 2007-01-09 12:58:35.000000000 -0800 @@ -0,0 +1,29 @@ +#include <new> + +extern "C" void free (void *); + +void +operator delete (void *ptr, const std::nothrow_t&) throw () +{ + if (ptr) + free (ptr); +} + +void +operator delete (void *ptr) throw () +{ + if (ptr) + free (ptr); +} + +void +operator delete[] (void *ptr) throw () +{ + ::operator delete (ptr); +} + +void +operator delete[] (void *ptr, const std::nothrow_t&) throw () +{ + ::operator delete (ptr); +} --- ld/testsuite/ld-elf/dl5.cc.new 2007-01-09 14:48:18.000000000 -0800 +++ ld/testsuite/ld-elf/dl5.cc 2007-01-09 14:46:22.000000000 -0800 @@ -0,0 +1,61 @@ +#include <stdio.h> +#include <stdlib.h> +#include <new> + +int pass = 0; + +void * +operator new (size_t sz, const std::nothrow_t&) throw () +{ + void *p; + pass++; + p = malloc(sz); + return p; +} + +void * +operator new (size_t sz) throw (std::bad_alloc) +{ + void *p; + pass++; + p = malloc(sz); + return p; +} + +void +operator delete (void *ptr) throw () +{ + pass++; + if (ptr) + free (ptr); +} + +class A +{ +public: + A() {} + ~A() { } + int a; + int b; +}; + + +int +main (void) +{ + A *bb = new A[10]; + delete [] bb; + bb = new (std::nothrow) A [10]; + delete [] bb; + + if (pass == 4) + { + printf ("PASS\n"); + return 0; + } + else + { + printf ("FAIL\n"); + return 1; + } +} --- ld/testsuite/ld-elf/dl5.out.new 2007-01-09 14:48:18.000000000 -0800 +++ ld/testsuite/ld-elf/dl5.out 2007-01-09 14:47:38.000000000 -0800 @@ -0,0 +1 @@ +PASS --- ld/testsuite/ld-elf/new.cc.new 2007-01-09 14:48:18.000000000 -0800 +++ ld/testsuite/ld-elf/new.cc 2007-01-09 11:49:37.000000000 -0800 @@ -0,0 +1,48 @@ +#include <new> +#include <exception_defines.h> + +using std::bad_alloc; + +extern "C" void *malloc (std::size_t); +extern "C" void abort (void); + +void * +operator new (std::size_t sz, const std::nothrow_t&) throw() +{ + void *p; + + /* malloc (0) is unpredictable; avoid it. */ + if (sz == 0) + sz = 1; + p = (void *) malloc (sz); + return p; +} + +void * +operator new (std::size_t sz) throw (std::bad_alloc) +{ + void *p; + + /* malloc (0) is unpredictable; avoid it. */ + if (sz == 0) + sz = 1; + p = (void *) malloc (sz); + while (p == 0) + { + ::abort(); + } + + return p; +} + +void* +operator new[] (std::size_t sz) throw (std::bad_alloc) +{ + return ::operator new(sz); +} + +void * +operator new[] (std::size_t sz, const std::nothrow_t& nothrow) throw() +{ + return ::operator new(sz, nothrow); +} --- ld/testsuite/ld-elf/shared.exp.new 2007-01-09 11:22:59.000000000 -0800 +++ ld/testsuite/ld-elf/shared.exp 2007-01-09 14:47:17.000000000 -0800 @@ -171,6 +171,9 @@ set build_cxx_tests { {"Build libdl3a.so with --dynamic-list-cpp-typeinfo" "-shared -Wl,--dynamic-list-cpp-typeinfo" "-fPIC" {dl3.cc} {} "libdl3c.so" "c++"} + {"Build libdnew.so with -Bsymbolic-functions -dynamic-list-cpp-new" + "-shared -Wl,-Bsymbolic-functions,--dynamic-list-cpp-new" "-fPIC" + {del.cc new.cc} {} "libnew.so" "c++"} } set run_cxx_tests { @@ -183,6 +186,9 @@ set run_cxx_tests { {"Run with libdl3c.so" "tmpdir/libdl3c.so" "" {dl3main.cc} "dl3c" "dl3a.out" "" "c++"} + {"Run with libnew.so" + "tmpdir/libnew.so" "" + {dl5.cc} "dl5" "dl5.out" "" "c++"} } run_cc_link_tests $build_cxx_tests