This is the mail archive of the binutils@sources.redhat.com 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]

[PATCH] Limited export of dynamic syms (elf32)


I have implemented a possibility for exporting only selected symbols
as dynamic symbols in the elf32 case.

Important gotcha:  I have not tested this on anything but elf32, so
I don't know if it breaks anything.

I've added an option '--retain-dynamic-symbols-file' which is completely
parallell to '--retain-symbols-file'.  If '-E' is given (export dynamic
symbols), '--retain-dynamic-symbols-file <filename>' will limit the
exported symbols to the symbols listed in the file <filename>.


For those who knows this part of the code, I'm sure my code is obvious.
It is a fairly straightforward copy of --retain-symbols-file.  I also
expect that it would be easy to add the support to non-elf32 builds.



Here is a quick description, including some gotchas:


bfd/elflink.h

I have added a function elf_export_symbol_filtered.  It is almost identical
to elf_export_symbol, but I need extra parameters, and I don't know the ld
code well enough to know if I'll get them automatically.  See the comment
at the top of the function.  I assume that I will always get the correct
parameter, in which case, this function could replace elf_export_symbol
instead.


I have also changed the call to do the export to the new function.
The old code is there too, in an "if (0)".  There is probably negligible
speed loss from using the filtered version in both cases, though
I haven't measured.



include/bfdlink.h

struct bfd_link_info: added the hash table of symbols to export.



ld/ldmain.c (and ldmain.h)

init the hash table of symbols to export.

Added a function to handle --retain_dynamic_symbols_file
(add_keepdynsyms_file), which is mostly a straightforward copy of
add_keepsyms_file.



ld/lexsup.c

Added the option (--retain_dynamic_symbols_file)


eirik
diff -ru src-2.11/bfd/elflink.h src-2.11-local/bfd/elflink.h
--- src-2.11/bfd/elflink.h	Tue Jan 23 11:45:53 2001
+++ src-2.11-local/bfd/elflink.h	Thu Aug 16 14:17:22 2001
@@ -28,6 +28,17 @@
   struct bfd_link_info *info;
 };
 
+
+/* This struct is used to pass the params to the
+ * elf_export_symbol_filtered function (through elf_hash_traverse)
+ */
+struct elf_export_symbol_filtered_params
+{
+	struct elf_info_failed *eif;
+	struct bfd_hash_table *keep_hash;
+};
+
+
 static boolean elf_link_add_object_symbols
   PARAMS ((bfd *, struct bfd_link_info *));
 static boolean elf_link_add_archive_symbols
@@ -38,6 +49,8 @@
 	   boolean *, boolean *, boolean *, boolean));
 static boolean elf_export_symbol
   PARAMS ((struct elf_link_hash_entry *, PTR));
+static boolean elf_export_symbol_filtered
+  PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf_fix_symbol_flags
   PARAMS ((struct elf_link_hash_entry *, struct elf_info_failed *));
 static boolean elf_adjust_dynamic_symbol
@@ -2960,8 +2973,17 @@
 
 	  eif.failed = false;
 	  eif.info = info;
-	  elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol,
-			          (PTR) &eif);
+	  if (0) /* Always do the filtered version */
+	  {
+	    elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol,
+			            (PTR) &eif);
+	  } else {
+	    struct elf_export_symbol_filtered_params params;
+	    params.eif=&eif;
+	    params.keep_hash=info->keep_dynsyms_hash;
+	    elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol_filtered,
+			            (PTR) &params);
+	  };
 	  if (eif.failed)
 	    return false;
 	}
@@ -3694,6 +3717,32 @@
 
   return true;
 }
+
+
+/* This routine is used to conditionally export all defined symbols into
+ * the dynamic symbol table.  It is called via elf_link_hash_traverse.
+ *
+ * This routine differs from elf_export_symbol in that it looks through
+ * a hash of symbols and only exports those that are found in that hash.
+ *
+ * The main reason for making a new function out of it, is to make sure
+ * that I get the right bfd_link_info.  If I can trust that eif->info (in
+ * elf_export_symbol) is the correct bfd_link_info, I could use that instead.
+ */
+static boolean
+elf_export_symbol_filtered(h, data)
+     struct elf_link_hash_entry *h;
+     PTR data;
+{
+  struct elf_export_symbol_filtered_params *params=(struct elf_export_symbol_filtered_params*) data;
+  if (params->keep_hash==NULL ||
+      bfd_hash_lookup (params->keep_hash, h->root.root.string, false, false) != NULL
+	  )
+    return elf_export_symbol(h, params->eif);
+  else
+    return true;
+};
+
 
 /* Look through the symbols which are defined in other shared
    libraries and referenced here.  Update the list of version
diff -ru src-2.11/include/bfdlink.h src-2.11-local/include/bfdlink.h
--- src-2.11/include/bfdlink.h	Tue Dec 12 20:53:02 2000
+++ src-2.11-local/include/bfdlink.h	Thu Aug 16 14:21:28 2001
@@ -268,6 +268,11 @@
 
   /* May be used to set DT_FLAGS_1 for ELF. */
   bfd_vma flags_1;
+
+  /* Hash table of dynamic symbols to export.  If NULL, export everything.
+   * Only has any effect if dynamic symbols are exported at all.
+   */
+  struct bfd_hash_table *keep_dynsyms_hash;
 };
 
 /* This structures holds a set of callback functions.  These are
diff -ru src-2.11/ld/ldmain.c src-2.11-local/ld/ldmain.c
--- src-2.11/ld/ldmain.c	Tue Dec 12 20:53:00 2000
+++ src-2.11-local/ld/ldmain.c	Thu Aug 16 14:23:03 2001
@@ -242,6 +242,7 @@
   link_info.new_dtags = false;
   link_info.flags = (bfd_vma) 0;
   link_info.flags_1 = (bfd_vma) 0;
+  link_info.keep_dynsyms_hash = NULL;
 
   ldfile_add_arch ("");
 
@@ -713,6 +714,70 @@
 
   link_info.strip = strip_some;
 }
+
+
+/* Handle the --retain-dynamic-symbols option.
+ * This is mostly a copy of add_keepsyms_file
+ */
+void
+add_keepdynsyms_file(filename)
+  const char * filename;
+{
+  FILE *file;
+  char *buf;
+  size_t bufsize;
+  int c;
+
+  file = fopen (filename, "r");
+  if (file == (FILE *) NULL)
+    {
+      bfd_set_error (bfd_error_system_call);
+      einfo ("%X%P: %s: %E\n", filename);
+      return;
+    }
+
+  if (link_info.keep_dynsyms_hash == NULL)
+  {
+    link_info.keep_dynsyms_hash = ((struct bfd_hash_table *)
+			   xmalloc (sizeof (struct bfd_hash_table)));
+    if (! bfd_hash_table_init (link_info.keep_dynsyms_hash, bfd_hash_newfunc))
+      einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
+  };
+
+  bufsize = 100;
+  buf = (char *) xmalloc (bufsize);
+
+  c = getc (file);
+  while (c != EOF)
+    {
+      while (isspace (c))
+	c = getc (file);
+
+      if (c != EOF)
+	{
+	  size_t len = 0;
+
+	  while (! isspace (c) && c != EOF)
+	    {
+	      buf[len] = c;
+	      ++len;
+	      if (len >= bufsize)
+		{
+		  bufsize *= 2;
+		  buf = xrealloc (buf, bufsize);
+		}
+	      c = getc (file);
+	    }
+
+	  buf[len] = '\0';
+
+	  if (bfd_hash_lookup (link_info.keep_dynsyms_hash, buf, true, true)
+	      == (struct bfd_hash_entry *) NULL)
+	    einfo (_("%P%F: bfd_hash_lookup for insertion failed: %E\n"));
+	}
+    }
+
+};
 
 /* Callbacks from the BFD linker routines.  */
 
diff -ru src-2.11/ld/ldmain.h src-2.11-local/ld/ldmain.h
--- src-2.11/ld/ldmain.h	Mon May  3 07:29:07 1999
+++ src-2.11-local/ld/ldmain.h	Thu Aug 16 14:17:23 2001
@@ -36,5 +36,6 @@
 extern void add_ysym PARAMS ((const char *));
 extern void add_wrap PARAMS ((const char *));
 extern void add_keepsyms_file PARAMS ((const char *filename));
+extern void add_keepdynsyms_file PARAMS ((const char *filename));
 
 #endif
diff -ru src-2.11/ld/lexsup.c src-2.11-local/ld/lexsup.c
--- src-2.11/ld/lexsup.c	Sun Jan 14 04:36:34 2001
+++ src-2.11-local/ld/lexsup.c	Thu Aug 16 14:17:23 2001
@@ -89,7 +89,8 @@
 #define OPTION_OFORMAT			(OPTION_NO_WHOLE_ARCHIVE + 1)
 #define OPTION_RELAX			(OPTION_OFORMAT + 1)
 #define OPTION_RETAIN_SYMBOLS_FILE	(OPTION_RELAX + 1)
-#define OPTION_RPATH			(OPTION_RETAIN_SYMBOLS_FILE + 1)
+#define OPTION_RETAIN_DYNAMIC_SYMBOLS_FILE  (OPTION_RETAIN_SYMBOLS_FILE + 1)
+#define OPTION_RPATH			(OPTION_RETAIN_DYNAMIC_SYMBOLS_FILE + 1)
 #define OPTION_RPATH_LINK		(OPTION_RPATH + 1)
 #define OPTION_SHARED			(OPTION_RPATH_LINK + 1)
 #define OPTION_SONAME			(OPTION_SHARED + 1)
@@ -330,6 +331,9 @@
   { {"retain-symbols-file", required_argument, NULL,
        OPTION_RETAIN_SYMBOLS_FILE},
       '\0', N_("FILE"), N_("Keep only symbols listed in FILE"), TWO_DASHES },
+  { {"retain-dynamic-symbols-file", required_argument, NULL,
+       OPTION_RETAIN_DYNAMIC_SYMBOLS_FILE},
+      '\0', N_("FILE"), N_("Keep only dynamic symbols listed in FILE"), TWO_DASHES },
   { {"rpath", required_argument, NULL, OPTION_RPATH},
       '\0', N_("PATH"), N_("Set runtime shared library search path"), ONE_DASH },
   { {"rpath-link", required_argument, NULL, OPTION_RPATH_LINK},
@@ -863,6 +867,11 @@
 	  break;
 	case OPTION_RETAIN_SYMBOLS_FILE:
 	  add_keepsyms_file (optarg);
+	  break;
+	case OPTION_RETAIN_DYNAMIC_SYMBOLS_FILE:
+	  add_keepdynsyms_file (optarg);
+	  /* Implied --export-dynamic */
+	  command_line.export_dynamic=true;
 	  break;
 	case 'S':
 	  link_info.strip = strip_debugger;

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