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]

Add a --localize-hidden option to objcopy


This patch adds a --localize-hidden option to objcopy.  As its name
suggests, it converts all global or weak STV_HIDDEN or STV_INTERNAL
symbols into local symbols.  It is equivalent to listing all such
symbols using separate -L options.

One potential use for this option is to help build flat uClinux
shared libraries.  The full process for building flat libraries
is described here:

    http://www.ucdot.org/article.pl?sid=03/11/25/1126257&mode=thread (m68k)
    http://docs.blackfin.uclinux.org/doku.php?id=adding_libraries (blackfin)

but basically, the user first builds a fully-linked ELF object for the
shared library, then converts it to flat format.  Code that uses the
shared library will then link against the ELF file using --just-symbols.
(This system is far from ideal, but it is used.)

One problem with using --just-symbols is that every global symbol in the
shared library will participate in the --just-sybmols link.  The user
therefore needs to localise any symbol that should not be exported.
The current procedure for doing this is to use objcopy with one -L option
for every symbol that must be localised.  For example, to quote from the
page linked above:

    m68k-elf-objcopy \
      -L _GLOBAL_OFFSET_TABLE_ \
      -L main \
      -L __main \
      -L lib_main \
      -L __do_global_dtors \
      -L __do_global_ctors    \
      -L __CTOR_LIST__ \
      -L __DTOR_LIST__        \
      -L _current_shared_library_a5_offset_        \
      libmylib.gdb

Unfortunately, this list tends to vary between toolchain and uClibc
releases and gets quite unwieldly for bigger libraries.

It would be nice to able to apply ELF-like visibility to flat shared
libraries too, with every hidden or internal symbol being ommitted
from the --just-symbols link.  --localize-hidden does this.

This might be stretching things a bit, but I can imagine cases where
--localize-symbols might be useful for ld -r links too.

The patch adds two testcases, one for an ELF file, and one no-op test
that should work on all targets.  Tested on m68k-elf and i386-mingw32.
OK to install?

Richard


binutils/
	* objcopy.c (localize_hidden): New variable.
	(OPTION_LOCALIZE_HIDDEN): New command_line_switch value.
	(copy_options): Add --localize-hidden.
	(copy_usage): Mention --localize-hidden.
	(is_hidden_symbol): New function.
	(filter_symbols): Handle localize_hidden.
	(copy_object): Call filter_symbols if localize_hidden.
	(copy_main): Handle OPTION_LOCALIZE_HIDDEN.
	* doc/binutils.texi (--localize-hidden): Document new option.

binutils/testsuite/
	* binutils-all/localize-hidden-1.s,
	* binutils-all/localize-hidden-1.d,
	* binutils-all/localize-hidden-2.s,
	* binutils-all/localize-hidden-2.d: New tests.
	* binutils-all/objcopy.exp: Run them.

Index: binutils/objcopy.c
===================================================================
RCS file: /cvs/src/src/binutils/objcopy.c,v
retrieving revision 1.95
diff -u -p -r1.95 objcopy.c
--- binutils/objcopy.c	28 Feb 2006 16:09:01 -0000	1.95
+++ binutils/objcopy.c	8 Jun 2006 11:24:45 -0000
@@ -190,6 +190,9 @@ static bfd_boolean remove_leading_char =
 /* Whether to permit wildcard in symbol comparison.  */
 static bfd_boolean wildcard = FALSE;
 
+/* True if --localize-hidden is in effect.  */
+static bfd_boolean localize_hidden = FALSE;
+
 /* List of symbols to strip, keep, localize, keep-global, weaken,
    or redefine.  */
 static struct symlist *strip_specific_list = NULL;
@@ -240,6 +243,7 @@ enum command_line_switch
     OPTION_STRIP_UNNEEDED_SYMBOL,
     OPTION_STRIP_UNNEEDED_SYMBOLS,
     OPTION_KEEP_SYMBOLS,
+    OPTION_LOCALIZE_HIDDEN,
     OPTION_LOCALIZE_SYMBOLS,
     OPTION_GLOBALIZE_SYMBOL,
     OPTION_GLOBALIZE_SYMBOLS,
@@ -328,6 +332,7 @@ static struct option copy_options[] =
   {"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS},
   {"keep-symbol", required_argument, 0, 'K'},
   {"keep-symbols", required_argument, 0, OPTION_KEEP_SYMBOLS},
+  {"localize-hidden", no_argument, 0, OPTION_LOCALIZE_HIDDEN},
   {"localize-symbol", required_argument, 0, 'L'},
   {"localize-symbols", required_argument, 0, OPTION_LOCALIZE_SYMBOLS},
   {"no-adjust-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
@@ -428,6 +433,7 @@ copy_usage (FILE *stream, int exit_statu
      --only-keep-debug             Strip everything but the debug information\n\
   -K --keep-symbol <name>          Do not strip symbol <name>\n\
      --keep-file-symbols           Do not strip file symbol(s)\n\
+     --localize-hidden             Turn all ELF hidden symbols into locals\n\
   -L --localize-symbol <name>      Force symbol <name> to be marked as a local\n\
      --globalize-symbol <name>     Force symbol <name> to be marked as a global\n\
   -G --keep-global-symbol <name>   Localize all symbols except <name>\n\
@@ -809,6 +815,24 @@ is_strip_section (bfd *abfd ATTRIBUTE_UN
   return FALSE;
 }
 
+/* Return true if SYM is a hidden symbol.  */
+
+static bfd_boolean
+is_hidden_symbol (asymbol *sym)
+{
+  elf_symbol_type *elf_sym;
+
+  elf_sym = elf_symbol_from (sym->the_bfd, sym);
+  if (elf_sym != NULL)
+    switch (ELF_ST_VISIBILITY (elf_sym->internal_elf_sym.st_other))
+      {
+      case STV_HIDDEN:
+      case STV_INTERNAL:
+	return TRUE;
+      }
+  return FALSE;
+}
+
 /* Choose which symbol entries to copy; put the result in OSYMS.
    We don't copy in place, because that confuses the relocs.
    Return the number of symbols to print.  */
@@ -955,7 +979,8 @@ filter_symbols (bfd *abfd, bfd *obfd, as
 	      && (flags & (BSF_GLOBAL | BSF_WEAK))
 	      && (is_specified_symbol (name, localize_specific_list)
 		  || (keepglobal_specific_list != NULL
-		      && ! is_specified_symbol (name, keepglobal_specific_list))))
+		      && ! is_specified_symbol (name, keepglobal_specific_list))
+		  || (localize_hidden && is_hidden_symbol (sym))))
 	    {
 	      sym->flags &= ~ (BSF_GLOBAL | BSF_WEAK);
 	      sym->flags |= BSF_LOCAL;
@@ -1532,6 +1557,7 @@ copy_object (bfd *ibfd, bfd *obfd)
       || strip_symbols == STRIP_UNNEEDED
       || strip_symbols == STRIP_NONDEBUG
       || discard_locals != LOCALS_UNDEF
+      || localize_hidden
       || strip_specific_list != NULL
       || keep_specific_list != NULL
       || localize_specific_list != NULL
@@ -3064,6 +3090,10 @@ copy_main (int argc, char *argv[])
 	  add_specific_symbols (optarg, &keep_specific_list);
 	  break;
 
+	case OPTION_LOCALIZE_HIDDEN:
+	  localize_hidden = TRUE;
+	  break;
+
 	case OPTION_LOCALIZE_SYMBOLS:
 	  add_specific_symbols (optarg, &localize_specific_list);
 	  break;
Index: binutils/doc/binutils.texi
===================================================================
RCS file: /cvs/src/src/binutils/doc/binutils.texi,v
retrieving revision 1.92
diff -u -p -r1.92 binutils.texi
--- binutils/doc/binutils.texi	17 May 2006 21:40:44 -0000	1.92
+++ binutils/doc/binutils.texi	8 Jun 2006 11:24:46 -0000
@@ -952,6 +952,7 @@ objcopy [@option{-F} @var{bfdname}|@opti
         [@option{-N} @var{symbolname}|@option{--strip-symbol=}@var{symbolname}]
         [@option{--strip-unneeded-symbol=}@var{symbolname}]
         [@option{-G} @var{symbolname}|@option{--keep-global-symbol=}@var{symbolname}]
+        [@option{--localize-hidden}]
         [@option{-L} @var{symbolname}|@option{--localize-symbol=}@var{symbolname}]
         [@option{--globalize-symbol=}@var{symbolname}]
         [@option{-W} @var{symbolname}|@option{--weaken-symbol=}@var{symbolname}]
@@ -1124,6 +1125,11 @@ Keep only symbol @var{symbolname} global
 to the file, so that they are not visible externally.  This option may
 be given more than once.
 
+@item --localize-hidden
+In an ELF object, mark all symbols that have hidden or internal visibility
+as local.  This option applies on top of symbol-specific localization options
+such as @option{-L}.
+
 @item -L @var{symbolname}
 @itemx --localize-symbol=@var{symbolname}
 Make symbol @var{symbolname} local to the file, so that it is not
Index: binutils/testsuite/binutils-all/localize-hidden-1.d
===================================================================
RCS file: binutils/testsuite/binutils-all/localize-hidden-1.d
diff -N binutils/testsuite/binutils-all/localize-hidden-1.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ binutils/testsuite/binutils-all/localize-hidden-1.d	8 Jun 2006 11:24:46 -0000
@@ -0,0 +1,17 @@
+#PROG: objcopy
+#readelf: --symbols
+#objcopy: --localize-hidden
+#name: --localize-hidden test 1
+#...
+.*: 0+1200 +0 +NOTYPE +LOCAL +HIDDEN +ABS +Lhidden
+.*: 0+1300 +0 +NOTYPE +LOCAL +INTERNAL +ABS +Linternal
+.*: 0+1400 +0 +NOTYPE +LOCAL +PROTECTED +ABS +Lprotected
+.*: 0+1100 +0 +NOTYPE +LOCAL +DEFAULT +ABS +Ldefault
+.*: 0+2200 +0 +NOTYPE +LOCAL +HIDDEN +ABS +Ghidden
+.*: 0+2300 +0 +NOTYPE +LOCAL +INTERNAL +ABS +Ginternal
+.*: 0+3200 +0 +NOTYPE +LOCAL +HIDDEN +ABS +Whidden
+.*: 0+3300 +0 +NOTYPE +LOCAL +INTERNAL +ABS +Winternal
+.*: 0+2100 +0 +NOTYPE +GLOBAL +DEFAULT +ABS +Gdefault
+.*: 0+2400 +0 +NOTYPE +GLOBAL +PROTECTED +ABS +Gprotected
+.*: 0+3100 +0 +NOTYPE +WEAK +DEFAULT +ABS +Wdefault
+.*: 0+3400 +0 +NOTYPE +WEAK +PROTECTED +ABS +Wprotected
Index: binutils/testsuite/binutils-all/localize-hidden-1.s
===================================================================
RCS file: binutils/testsuite/binutils-all/localize-hidden-1.s
diff -N binutils/testsuite/binutils-all/localize-hidden-1.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ binutils/testsuite/binutils-all/localize-hidden-1.s	8 Jun 2006 11:24:46 -0000
@@ -0,0 +1,36 @@
+	.globl		Gdefault
+	.globl		Ghidden
+	.globl		Ginternal
+	.globl		Gprotected
+
+	.weak		Wdefault
+	.weak		Whidden
+	.weak		Winternal
+	.weak		Wprotected
+
+	.hidden		Lhidden
+	.hidden		Ghidden
+	.hidden		Whidden
+
+	.internal	Linternal
+	.internal	Ginternal
+	.internal	Winternal
+
+	.protected	Lprotected
+	.protected	Gprotected
+	.protected	Wprotected
+
+	.equ		Ldefault, 0x1100
+	.equ		Lhidden, 0x1200
+	.equ		Linternal, 0x1300
+	.equ		Lprotected, 0x1400
+
+	.equ		Gdefault, 0x2100
+	.equ		Ghidden, 0x2200
+	.equ		Ginternal, 0x2300
+	.equ		Gprotected, 0x2400
+
+	.equ		Wdefault, 0x3100
+	.equ		Whidden, 0x3200
+	.equ		Winternal, 0x3300
+	.equ		Wprotected, 0x3400
Index: binutils/testsuite/binutils-all/localize-hidden-2.d
===================================================================
RCS file: binutils/testsuite/binutils-all/localize-hidden-2.d
diff -N binutils/testsuite/binutils-all/localize-hidden-2.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ binutils/testsuite/binutils-all/localize-hidden-2.d	8 Jun 2006 11:24:46 -0000
@@ -0,0 +1,7 @@
+#PROG: objcopy
+#nm: -n
+#objcopy: --localize-hidden
+#name: --localize-hidden test 2
+#...
+0+100 A G
+#pass
Index: binutils/testsuite/binutils-all/localize-hidden-2.s
===================================================================
RCS file: binutils/testsuite/binutils-all/localize-hidden-2.s
diff -N binutils/testsuite/binutils-all/localize-hidden-2.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ binutils/testsuite/binutils-all/localize-hidden-2.s	8 Jun 2006 11:24:46 -0000
@@ -0,0 +1,2 @@
+	.globl	G
+	.equ	G,0x100
Index: binutils/testsuite/binutils-all/objcopy.exp
===================================================================
RCS file: /cvs/src/src/binutils/testsuite/binutils-all/objcopy.exp,v
retrieving revision 1.36
diff -u -p -r1.36 objcopy.exp
--- binutils/testsuite/binutils-all/objcopy.exp	3 May 2006 14:21:18 -0000	1.36
+++ binutils/testsuite/binutils-all/objcopy.exp	8 Jun 2006 11:24:46 -0000
@@ -728,3 +728,8 @@ if [is_elf_format] {
 
 run_dump_test "copy-2"
 run_dump_test "copy-3"
+
+if [is_elf_format] {
+    run_dump_test "localize-hidden-1"
+}
+run_dump_test "localize-hidden-2"


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