Index: gold/i386.cc =================================================================== RCS file: /cvs/src/src/gold/i386.cc,v retrieving revision 1.86 diff -u -u -p -r1.86 i386.cc --- gold/i386.cc 24 Mar 2009 00:31:28 -0000 1.86 +++ gold/i386.cc 5 Jun 2009 01:42:09 -0000 @@ -155,6 +155,19 @@ class Target_i386 : public Target_freebs do_is_defined_by_abi(const Symbol* sym) const { return strcmp(sym->name(), "___tls_get_addr") == 0; } + // Return whether a symbol name implies a local label. The UnixWare + // 2.1 cc generates temporary symbols that start with .X, so we + // recognize them here. FIXME: do other SVR4 compilers also use .X?. + // If so, we should move the .X recognition into + // Target::do_is_local_label_name. + bool + do_is_local_label_name(const char* name) const + { + if (name[0] == '.' && name[1] == 'X') + return true; + return Target::do_is_local_label_name(name); + } + // Return the size of the GOT section. section_size_type got_size() Index: gold/object.cc =================================================================== RCS file: /cvs/src/src/gold/object.cc,v retrieving revision 1.91 diff -u -u -p -r1.91 object.cc --- gold/object.cc 22 May 2009 18:31:22 -0000 1.91 +++ gold/object.cc 5 Jun 2009 01:42:09 -0000 @@ -1432,6 +1432,7 @@ Sized_relobj::do_count unsigned int dyncount = 0; // Skip the first, dummy, symbol. psyms += sym_size; + bool discard_locals = parameters->options().discard_locals(); for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size) { elfcpp::Sym sym(psyms); @@ -1476,8 +1477,28 @@ Sized_relobj::do_count continue; } - // Add the symbol to the symbol table string pool. + // If --discard-locals option is used, discard all temporary local + // symbols. These symbols start with system-specific local label + // prefixes, typically .L for ELF system. We want to be compatible + // with GNU ld so here we essentially use the same check in + // bfd_is_local_label(). The code is different because we already + // know that: + // + // - the symbol is local and thus cannot have global or weak binding. + // - the symbol is not a section symbol. + // - the symbol has a name. + // const char* name = pnames + sym.get_st_name(); + if (discard_locals + && sym.get_st_type() != elfcpp::STT_FILE + && parameters->target().is_local_label_name(name)) + { + lv.set_no_output_symtab_entry(); + gold_assert(!lv.needs_output_dynsym_entry()); + continue; + } + + // Add the symbol to the symbol table string pool. pool->add(name, true, NULL); ++count; Index: gold/options.h =================================================================== RCS file: /cvs/src/src/gold/options.h,v retrieving revision 1.98 diff -u -u -p -r1.98 options.h --- gold/options.h 19 May 2009 22:14:17 -0000 1.98 +++ gold/options.h 5 Jun 2009 01:42:09 -0000 @@ -645,6 +645,9 @@ class General_options N_("Try to detect violations of the One Definition Rule"), NULL); + DEFINE_bool(discard_locals, options::TWO_DASHES, 'X', false, + N_("Delete all temporary local symbols"), NULL); + DEFINE_bool(dynamic_list_data, options::TWO_DASHES, '\0', false, N_("Add data symbols to dynamic symbols"), NULL); Index: gold/target.h =================================================================== RCS file: /cvs/src/src/gold/target.h,v retrieving revision 1.32 diff -u -u -p -r1.32 target.h --- gold/target.h 24 Mar 2009 00:31:29 -0000 1.32 +++ gold/target.h 5 Jun 2009 01:42:09 -0000 @@ -173,6 +173,12 @@ class Target adjust_elf_header(unsigned char* view, int len) const { return this->do_adjust_elf_header(view, len); } + // Return whether NAME is a local label name. This is used to implement the + // --discard-locals options. + bool + is_local_label_name(const char* name) const + { return this->do_is_local_label_name(name); } + protected: // This struct holds the constant information for a child class. We // use a struct to avoid the overhead of virtual function calls for @@ -239,6 +245,33 @@ class Target do_adjust_elf_header(unsigned char*, int) const { } + // Virtual function which may be overriden by the child class. + virtual bool + do_is_local_label_name(const char* name) const + { + // The logic is the same as that in _bfd_elf_is_local_label_name(). + + // Normal local symbols start with ``.L''. + if (name[0] == '.' && name[1] == 'L') + return true; + + // At least some SVR4 compilers (e.g., UnixWare 2.1 cc) generate + // DWARF debugging symbols starting with ``..''. + if (name[0] == '.' && name[1] == '.') + return true; + + // gcc will sometimes generate symbols beginning with ``_.L_'' when + // emitting DWARF debugging output. I suspect this is actually a + // small bug in gcc (it calls ASM_OUTPUT_LABEL when it should call + // ASM_GENERATE_INTERNAL_LABEL, and this causes the leading + // underscore to be emitted on some ELF targets). For ease of use, + // we treat such symbols as local. + if (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_') + return true; + + return false; + } + private: Target(const Target&); Target& operator=(const Target&); Index: gold/testsuite/Makefile.am =================================================================== RCS file: /cvs/src/src/gold/testsuite/Makefile.am,v retrieving revision 1.91 diff -u -u -p -r1.91 Makefile.am --- gold/testsuite/Makefile.am 26 May 2009 22:52:56 -0000 1.91 +++ gold/testsuite/Makefile.am 5 Jun 2009 01:42:09 -0000 @@ -1074,5 +1074,17 @@ alt/libexclude_libs_test_3.a: exclude_li test -d alt || mkdir -p alt $(TEST_AR) rc $@ $^ +check_PROGRAMS += discard_locals_test +check_SCRIPTS += discard_locals_test.sh +check_DATA += discard_locals_test.syms +MOSTLYCLEANFILES += discard_locals_test.syms +discard_locals_test_SOURCES = discard_locals_test.c +discard_locals_test_LDFLAGS = -Bgcctestdir/ -Wl,--discard-locals +discard_locals_test.syms: discard_locals_test + $(TEST_READELF) -sW $< >$@ 2>/dev/null +# '-Wa,--keep-locals' is required to preserve the local label used for testing. +discard_locals_test.o: discard_locals_test.c + $(COMPILE) -c -Wa,--keep-locals -o $@ $< + endif GCC endif NATIVE_LINKER Index: gold/testsuite/Makefile.in =================================================================== RCS file: /cvs/src/src/gold/testsuite/Makefile.in,v retrieving revision 1.96 diff -u -u -p -r1.96 Makefile.in --- gold/testsuite/Makefile.in 26 May 2009 22:52:56 -0000 1.96 +++ gold/testsuite/Makefile.in 5 Jun 2009 01:42:09 -0000 @@ -318,12 +318,17 @@ check_PROGRAMS = object_unittest$(EXEEXT @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_2.err \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_3.err \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_4.err -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_24 = exclude_libs_test -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_25 = exclude_libs_test.sh -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_26 = exclude_libs_test.syms -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_27 = exclude_libs_test.syms libexclude_libs_test_1.a \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ libexclude_libs_test_2.a alt/libexclude_libs_test_3.a - +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_24 = exclude_libs_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_25 = exclude_libs_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test.sh +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_26 = exclude_libs_test.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test.syms +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_27 = exclude_libs_test.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ libexclude_libs_test_1.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ libexclude_libs_test_2.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/libexclude_libs_test_3.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test.syms subdir = testsuite DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -429,7 +434,8 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_3$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_4$(EXEEXT) @GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_17 = \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ exclude_libs_test$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exclude_libs_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test$(EXEEXT) basic_pic_test_SOURCES = basic_pic_test.c basic_pic_test_OBJECTS = basic_pic_test.$(OBJEXT) basic_pic_test_LDADD = $(LDADD) @@ -488,6 +494,14 @@ am__copy_test_SOURCES_DIST = copy_test.c @GCC_TRUE@@NATIVE_LINKER_TRUE@am_copy_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ copy_test.$(OBJEXT) copy_test_OBJECTS = $(am_copy_test_OBJECTS) +am__discard_locals_test_SOURCES_DIST = discard_locals_test.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_discard_locals_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test.$(OBJEXT) +discard_locals_test_OBJECTS = $(am_discard_locals_test_OBJECTS) +discard_locals_test_LDADD = $(LDADD) +discard_locals_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__exception_same_shared_test_SOURCES_DIST = exception_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_same_shared_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.$(OBJEXT) @@ -891,6 +905,7 @@ SOURCES = $(libgoldtest_a_SOURCES) basic $(binary_test_SOURCES) $(binary_unittest_SOURCES) \ $(common_test_1_SOURCES) $(constructor_static_test_SOURCES) \ $(constructor_test_SOURCES) $(copy_test_SOURCES) \ + $(discard_locals_test_SOURCES) \ $(exception_same_shared_test_SOURCES) \ $(exception_separate_shared_12_test_SOURCES) \ $(exception_separate_shared_21_test_SOURCES) \ @@ -944,6 +959,7 @@ DIST_SOURCES = $(libgoldtest_a_SOURCES) $(am__constructor_static_test_SOURCES_DIST) \ $(am__constructor_test_SOURCES_DIST) \ $(am__copy_test_SOURCES_DIST) \ + $(am__discard_locals_test_SOURCES_DIST) \ $(am__exception_same_shared_test_SOURCES_DIST) \ $(am__exception_separate_shared_12_test_SOURCES_DIST) \ $(am__exception_separate_shared_21_test_SOURCES_DIST) \ @@ -1519,6 +1535,8 @@ binary_unittest_SOURCES = binary_unittes @GCC_TRUE@@NATIVE_LINKER_TRUE@exclude_libs_test_LDADD = -lexclude_libs_test_1 -lexclude_libs_test_2 \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/libexclude_libs_test_3.a +@GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_test_SOURCES = discard_locals_test.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_test_LDFLAGS = -Bgcctestdir/ -Wl,--discard-locals all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am @@ -1605,6 +1623,9 @@ constructor_test$(EXEEXT): $(constructor copy_test$(EXEEXT): $(copy_test_OBJECTS) $(copy_test_DEPENDENCIES) @rm -f copy_test$(EXEEXT) $(CXXLINK) $(copy_test_LDFLAGS) $(copy_test_OBJECTS) $(copy_test_LDADD) $(LIBS) +discard_locals_test$(EXEEXT): $(discard_locals_test_OBJECTS) $(discard_locals_test_DEPENDENCIES) + @rm -f discard_locals_test$(EXEEXT) + $(LINK) $(discard_locals_test_LDFLAGS) $(discard_locals_test_OBJECTS) $(discard_locals_test_LDADD) $(LIBS) exception_same_shared_test$(EXEEXT): $(exception_same_shared_test_OBJECTS) $(exception_same_shared_test_DEPENDENCIES) @rm -f exception_same_shared_test$(EXEEXT) $(CXXLINK) $(exception_same_shared_test_LDFLAGS) $(exception_same_shared_test_OBJECTS) $(exception_same_shared_test_LDADD) $(LIBS) @@ -1882,6 +1903,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_test_1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constructor_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/copy_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/discard_locals_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exception_test_1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exception_test_2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exception_test_main.Po@am__quote@ @@ -2613,6 +2635,11 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@alt/libexclude_libs_test_3.a: exclude_libs_test_3.o @GCC_TRUE@@NATIVE_LINKER_TRUE@ test -d alt || mkdir -p alt @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AR) rc $@ $^ +@GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_test.syms: discard_locals_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -sW $< >$@ 2>/dev/null +# '-Wa,--keep-locals' is required to preserve the local label used for testing. +@GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_test.o: discard_locals_test.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -Wa,--keep-locals -o $@ $< # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: Index: gold/testsuite/discard_locals_test.c =================================================================== RCS file: gold/testsuite/discard_locals_test.c diff -N gold/testsuite/discard_locals_test.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gold/testsuite/discard_locals_test.c 5 Jun 2009 01:42:09 -0000 @@ -0,0 +1,40 @@ +/* discard_locals_test.c -- test --discard-locals option. + + Copyright 2009 Free Software Foundation, Inc. + Doug Kwan . + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. + + This is a test of a common symbol in the main program and a + versioned symbol in a shared library. The common symbol in the + main program should override the shared library symbol. */ + +int +main (void) +{ + /* local symbol format for generic ELF target. */ + asm (".Lshould_be_discarded:"); + +#ifdef __i386__ + /* additional local symbol format for the i386 target. */ + asm (".Xshould_be_discarded:"); +#endif + + return 0; +} + Index: gold/testsuite/discard_locals_test.sh =================================================================== RCS file: gold/testsuite/discard_locals_test.sh diff -N gold/testsuite/discard_locals_test.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gold/testsuite/discard_locals_test.sh 5 Jun 2009 01:42:09 -0000 @@ -0,0 +1,44 @@ +#!/bin/sh + +# discard_locals_test.sh -- test that local symbols are discarded. + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Doug Kwan + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with exclude_libs_test.c, a C source file +# linked with option -Wl,--exclude-libs. We run readelf on +# the resulting executable and check that symbols from two test library +# archives are correctly hidden or left unmodified. + +check() +{ + file=$1 + + found=`egrep "should_be_discarded" $file` + if test -n "$found"; then + echo "These local symbols are not discarded in $file:" + echo "$found" + exit 1 + fi +} + +check "discard_locals_test.syms" + +exit 0