This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Add a --localize-hidden option to objcopy
- From: Richard Sandiford <richard at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Tue, 13 Jun 2006 14:49:17 +0100
- Subject: 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"