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: PATCH: new linker option for shared library COMDAT optimization


On Fri, Feb 17, 2012 at 11:41:03AM -0700, Sandra Loosemore wrote:
> The slight wrinkle in this scheme is that the ELF specification
> defines COMDAT groups as an attribute of relocatable files only, not
> shared objects.  So we cannot say definitely that a shared object
> provides a named COMDAT group.  The expedient hack I've adopted is
> to consider that a shared library provides a COMDAT group if it
> provides weak definitions for all symbols defined in sections that
> make up the group.

I wondered how robust this will prove to be.  So I wrote a patch for
nm to print out symbols defined in linkonce or comdat group sections,
and had a look at a powerpc-linux libstdc++ build.

$ find . -name \*.o | xargs ~/build/ppc/bin/binutils/nm-new -g -L | sed -n -e 's,[^ ][^ ]* [^ ][^ ]* ,,p' | sort | uniq > /tmp/xxx
$ nm -D src/.libs/libstdc++.so.6 | sed -n -e 's,[^ ][^ ]* [^ ][^ ]* ,,p' | sort | uniq > /tmp/yyy
$ diff -u /tmp/xxx /tmp/yyy
[snip]
-DW.ref.__gxx_personality_v0
-DW.ref._ZTIN10__cxxabiv115__forced_unwindE
-DW.ref._ZTISt9bad_alloc
-DW.ref._ZTISt9exception
-_X_ZNKSbIwSt11char_traitsIwESaIwEE11_M_disjunctEPKw
-_X_ZNKSbIwSt11char_traitsIwESaIwEE15_M_check_lengthEjjPKc
-_X_ZNKSs11_M_disjunctEPKc
-_X_ZNKSs15_M_check_lengthEjjPKc
-_X_ZNKSt13basic_fstreamIcSt11char_traitsIcEE7is_openEv
[snip]
$ diff -u /tmp/xxx /tmp/yyy | grep '^-[^-]' | wc -l
516
$ wc -l /tmp/xxx
3138 /tmp/xxx

That's rather a lot of missing symbols.  I think for this to work you
need another linker option to export all global symbols defined in
comdat sections.  Then, given that you will need to build shared
libraries differently, it would be a much better idea to mark them as
supporting shared-comdat, perhaps by exporting each comdat signature
symbol.  If you did that, you could probably dispense with all the
code you've written to match symbols..

-- 
Alan Modra
Australia Development Lab, IBM
Index: binutils/nm.c
===================================================================
RCS file: /cvs/src/src/binutils/nm.c,v
retrieving revision 1.69
diff -u -p -r1.69 nm.c
--- binutils/nm.c	16 Jan 2012 08:43:20 -0000	1.69
+++ binutils/nm.c	20 Feb 2012 23:38:27 -0000
@@ -140,6 +140,7 @@ static struct output_fns *format = &form
 static int do_demangle = 0;	/* Pretty print C++ symbol names.  */
 static int external_only = 0;	/* Print external symbols only.  */
 static int defined_only = 0;	/* Print defined symbols only.  */
+static int linkonce_only = 0;	/* Print symbols in linkonce sections only.  */
 static int no_sort = 0;		/* Don't sort; print syms in order found.  */
 static int print_debug_syms = 0;/* Print debugger-only symbols too.  */
 static int print_armap = 0;	/* Describe __.SYMDEF data in archive files.  */
@@ -194,6 +195,7 @@ static struct option long_options[] =
   {"dynamic", no_argument, &dynamic, 1},
   {"extern-only", no_argument, &external_only, 1},
   {"format", required_argument, 0, 'f'},
+  {"linkonce-only", no_argument, &linkonce_only, 1},
   {"help", no_argument, 0, 'h'},
   {"line-numbers", no_argument, 0, 'l'},
   {"no-cplus", no_argument, &do_demangle, 0},  /* Linux compatibility.  */
@@ -242,6 +244,7 @@ usage (FILE *stream, int status)
   -g, --extern-only      Display only external symbols\n\
   -l, --line-numbers     Use debugging information to find a filename and\n\
                            line number for each symbol\n\
+  -L, --linkonce-only    Display only symbols defined in linkonce sections\n\
   -n, --numeric-sort     Sort symbols numerically by address\n\
   -o                     Same as -A\n\
   -p, --no-sort          Do not sort the symbols\n\
@@ -402,6 +405,15 @@ print_symdef_entry (bfd *abfd)
     }
 }
 
+static inline int
+is_elf_comdat (asection *sec)
+{
+  return (sec->owner != NULL
+	  && bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
+	  && elf_sec_group (sec) != NULL
+	  && (elf_sec_group (sec)->flags & SEC_LINK_ONCE) != 0);
+}
+
 /* Choose which symbol entries to print;
    compact them downward to get rid of the rest.
    Return the number of symbols to be printed.  */
@@ -445,6 +457,12 @@ filter_symbols (bfd *abfd, bfd_boolean i
 	keep = 1;
 
       if (keep
+	  && linkonce_only
+	  && !((sym->section->flags & SEC_LINK_ONCE) != 0
+	       || is_elf_comdat (sym->section)))
+	keep = 0;
+
+      if (keep
 	  && ! print_debug_syms
 	  && (sym->flags & BSF_DEBUGGING) != 0)
 	keep = 0;
@@ -1545,7 +1563,7 @@ main (int argc, char **argv)
   bfd_init ();
   set_default_bfd_target ();
 
-  while ((c = getopt_long (argc, argv, "aABCDef:gHhlnopPrSst:uvVvX:",
+  while ((c = getopt_long (argc, argv, "aABCDef:gHhlLnopPrSst:uvVvX:",
 			   long_options, (int *) 0)) != EOF)
     {
       switch (c)
@@ -1592,6 +1610,9 @@ main (int argc, char **argv)
 	case 'l':
 	  line_numbers = 1;
 	  break;
+	case 'L':
+	  linkonce_only = 1;
+	  break;
 	case 'n':
 	case 'v':
 	  no_sort = 0;

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