Is it possible to hide some symbols in linking shared library?

mpsuzuki@hiroshima-u.ac.jp mpsuzuki@hiroshima-u.ac.jp
Tue Jan 26 08:49:00 GMT 2010


Dear GNU ld developers,

I'm looking for the portable method to hide some symbols
in a shared library when an executable or a binary is being
linked with the library.

Background
----------

Since freetype-2.2.x, FreeType2 does not install the header
files that defines internal functions. It was to improve the
forward binary compatibility by preventing the references to
internal functions, because they can be optimized out, added,
changed or removed.

However, for backward compatibility with "rogue clients"
referring internal functions, still shared library of FreeType2
exports all symbols on Unix platforms. As a result, the
prevention against the linking with the internal functions
is incompleted. Current prevention is in cpp, cc1 level,
not in ld level.

What I want to do
-----------------

I want to realize following 2 conditions:

C1) a shared library exports all symbols for runtime linker.

C2) when a developer links new binary with a shared library,
    the linker ignores some "blacklisted" symbols as if they
    cannot be resolved.

If possible, I want to realize C2 by the linker script.
The number of internal functions is about 100,
the specification by the commandline options is slightly
too lengthy.

# Although pkg-config can hold the lengthy options,
# there are too many developers linking without pkg-config.
# Especially, I guess, the developers dealing with legacy
# rogue clients may use GNU ld but may not use pkg-config.

--

Now I don't have smart idea to make the symbol resolver to
ignore a list of symbols (and how to construct such list 
in linker script). Thus I tried to extend BFD symbol name
wrapping feature.

Following patch adds new option "--wrap-symbols-file FILE"
that loads a list of symbols from FILE, and wrap all symbols
in the list. The error message of the linker is not intuitive
to indicate the deprecated reference to internal symbols,
but the prevention itself is OK.

Is there any better method to prevent the reference to
"blacklisted" symbols?

Regards,
mpsuzuki


diff --git a/ld/ldmain.h b/ld/ldmain.h
index 57ce8d7..7f2ae40 100644
--- a/ld/ldmain.h
+++ b/ld/ldmain.h
@@ -45,5 +45,6 @@ extern int overflow_cutoff_limit;
 extern void add_ysym (const char *);
 extern void add_wrap (const char *);
 extern void add_keepsyms_file (const char *);
+extern void add_wrapsyms_file (const char *);
 
 #endif
diff --git a/ld/lexsup.c b/ld/lexsup.c
index b992fca..5db5014 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -131,6 +131,7 @@ enum option_values
   OPTION_ADD_DT_NEEDED_FOR_REGULAR,
   OPTION_NO_ADD_DT_NEEDED_FOR_REGULAR,
   OPTION_WRAP,
+  OPTION_WRAP_SYMBOLS_FILE,
   OPTION_FORCE_EXE_SUFFIX,
   OPTION_GC_SECTIONS,
   OPTION_NO_GC_SECTIONS,
@@ -590,6 +591,9 @@ static const struct ld_option ld_options[] =
     TWO_DASHES },
   { {"wrap", required_argument, NULL, OPTION_WRAP},
     '\0', N_("SYMBOL"), N_("Use wrapper functions for SYMBOL"), TWO_DASHES },
+  { {"wrap-symbols-file", required_argument, NULL,
+     OPTION_WRAP_SYMBOLS_FILE},
+    '\0', N_("FILE"), N_("Wrap symbols listed in FILE"), TWO_DASHES },
 };
 
 #define OPTION_COUNT ARRAY_SIZE (ld_options)
@@ -1144,6 +1148,9 @@ parse_args (unsigned argc, char **argv)
 	case OPTION_RETAIN_SYMBOLS_FILE:
 	  add_keepsyms_file (optarg);
 	  break;
+	case OPTION_WRAP_SYMBOLS_FILE:
+	  add_wrapsyms_file (optarg);
+	  break;
 	case 'S':
 	  link_info.strip = strip_debugger;
 	  break;
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 08679ec..4b3cd56 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -707,6 +707,61 @@ add_wrap (const char *name)
     einfo (_("%P%F: bfd_hash_lookup failed: %E\n"));
 }
 
+/* Handle the -wrap-symbols-file option.  */
+
+void
+add_wrapsyms_file (const char *filename)
+{
+  FILE *file;
+  char *buf;
+  size_t bufsize;
+  int c;
+
+  if (link_info.wrap_hash != NULL)
+    einfo (_("%X%P: error: --retain-symbols-file can be used only once, without --wrap\n"));
+
+  file = fopen (filename, "r");
+  if (file == NULL)
+    {
+      bfd_set_error (bfd_error_system_call);
+      einfo ("%X%P: %s: %E\n", filename);
+      return;
+    }
+
+  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 = (char *) xrealloc (buf, bufsize);
+		}
+	      c = getc (file);
+	    }
+
+	  buf[len] = '\0';
+
+          add_wrap (buf);
+	}
+    }
+
+  free (buf);
+}
+
 /* Handle the -retain-symbols-file option.  */
 
 void



More information about the Binutils mailing list