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: Is it possible to hide some symbols in linking shared library?


Dear Ian,

On Tue, 26 Jan 2010 07:56:49 -0800
Ian Lance Taylor <iant@google.com> wrote:

>mpsuzuki@hiroshima-u.ac.jp writes:
>
>> 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.
>
>Sounds like you want a version script.  I admit I'm not sure how to
>move a shared library which does not use a version script to one that
>does without retaining the same set of symbols, but at least you can
>set yourself up for future fixes of this sort.

Thank you for kind advise to my silly question, I will try.
The most popular libraries using version script would be GNU
libc, FreeBSD libc etc, but they are huge and fundamental
project. If you know any small & portable library using symbol
versioning, please let me know.

Regards,
mpsuzuki


Anyway, I did a small experiment by introducing new command
"ERASE()" for GNU ld script. However, it is ugly implementation
and I'm not pushing. Just for the explanation what I wanted
to do.

diff --git a/ld/ldlex.l b/ld/ldlex.l
index c6a0254..b351575 100644
--- a/ld/ldlex.l
+++ b/ld/ldlex.l
@@ -259,6 +259,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 <EXPRESSION,BOTH,SCRIPT>"ASSERT"	{ RTOKEN(ASSERT_K); }
 <BOTH,SCRIPT>"ENTRY"			{ RTOKEN(ENTRY);}
 <BOTH,SCRIPT,MRI>"EXTERN"		{ RTOKEN(EXTERN);}
+<BOTH,SCRIPT>"ERASE"			{ RTOKEN(ERASE);}
 <EXPRESSION,BOTH,SCRIPT>"NEXT"		{ RTOKEN(NEXT);}
 <EXPRESSION,BOTH,SCRIPT>"sizeof_headers"	{ RTOKEN(SIZEOF_HEADERS);}
 <EXPRESSION,BOTH,SCRIPT>"SIZEOF_HEADERS"	{ RTOKEN(SIZEOF_HEADERS);}
diff --git a/ld/ldgram.y b/ld/ldgram.y
index 49d9ff1..7dc8a42 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -145,7 +145,7 @@ static int error_index;
 %type <name>  filename
 %token CHIP LIST SECT ABSOLUTE  LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K
 %token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
-%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
+%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN ERASE START
 %token <name> VERS_TAG VERS_IDENTIFIER
 %token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
 %token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL
@@ -245,6 +245,7 @@ mri_script_command:
 		{ mri_truncate ((unsigned int) $2.integer); }
 	|	CASE casesymlist
 	|	EXTERN extern_name_list
+	|	ERASE erase_name_list
 	|	INCLUDE filename
 		{ ldlex_script (); ldfile_open_command_file($2); }
 		mri_script_lines END
@@ -294,6 +295,20 @@ extern_name_list_body:
 			{ ldlang_add_undef ($3); }
 	;
 
+erase_name_list:
+	{ ldlex_expression (); }
+	erase_name_list_body
+	{ ldlex_popstate (); }
+
+erase_name_list_body:
+	  NAME
+			{ ldlang_erase_a_defined_symbol ($1); }
+	| erase_name_list_body NAME
+			{ ldlang_erase_a_defined_symbol ($2); }
+	| erase_name_list_body ',' NAME
+			{ ldlang_erase_a_defined_symbol ($3); }
+	;
+
 script_file:
 	{ ldlex_both(); }
 	ifile_list
@@ -350,6 +365,7 @@ ifile_p1:
 		  lang_add_nocrossref ($3);
 		}
 	|	EXTERN '(' extern_name_list ')'
+	|	ERASE '(' erase_name_list ')'
 	|	INSERT_K AFTER NAME
 		{ lang_add_insert ($3, 0); }
 	|	INSERT_K BEFORE NAME
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 58d03f0..df435b4 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -437,6 +437,7 @@ struct lang_definedness_hash_entry
 {
   struct bfd_hash_entry root;
   int iteration;
+  int erased; /* XXX: remove when BFD hash is enabled to delete an entry */
 };
 
 /* Used by place_orphan to keep track of orphan sections and statements.  */
@@ -563,6 +564,8 @@ extern lang_output_section_statement_type *lang_output_section_statement_lookup
   (const char *, int, bfd_boolean);
 extern lang_output_section_statement_type *next_matching_output_section_statement
   (lang_output_section_statement_type *, int);
+extern void ldlang_erase_a_defined_symbol
+  (const char *const);
 extern void ldlang_add_undef
   (const char *const);
 extern void lang_add_output_format
diff --git a/ld/ldlang.c b/ld/ldlang.c
index fd75a5b..9557a06 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -3204,6 +3204,7 @@ lang_definedness_newfunc (struct bfd_hash_entry *entry,
     einfo (_("%P%F: bfd_hash_allocate failed creating symbol %s\n"), name);
 
   ret->iteration = -1;
+  ret->erased = -1; /* XXX: remove when BFD hash is enabled to delete an entry */
   return &ret->root;
 }
 
@@ -3250,12 +3251,34 @@ lang_update_definedness (const char *name, struct bfd_link_hash_entry *h)
   if (h->type != bfd_link_hash_undefined
       && h->type != bfd_link_hash_common
       && h->type != bfd_link_hash_new
+      && defentry->erased < 1 /* XXX: remove when BFD hash is enabled to delete an entry */
       && defentry->iteration == -1)
     return;
 
   defentry->iteration = lang_statement_iteration;
 }
 
+void
+ldlang_erase_a_defined_symbol (const char *const name)
+{
+  struct lang_definedness_hash_entry *dh;
+  struct bfd_link_hash_entry *lh;
+
+  dh = (struct lang_definedness_hash_entry *)
+       bfd_hash_lookup (&lang_definedness_table, name, TRUE, FALSE);
+
+  if ( !dh ) /* inexistent symbol cannot be erased */
+    return;
+
+  dh->erased = 1; /* XXX: remove when BFD hash is enabled to delete an entry */
+
+  lh = bfd_wrapped_link_hash_lookup( link_info.output_bfd, &link_info, name, FALSE, FALSE, TRUE );
+  if ( !lh )
+    return;
+
+  lh->type = bfd_link_hash_undefined;
+}
+
 /* Add the supplied name to the symbol table as an undefined reference.
    This is a two step process as the symbol table doesn't even exist at
    the time the ld command line is processed.  First we put the name


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