More section layout code.
authorIan Lance Taylor <iant@google.com>
Tue, 26 Sep 2006 21:00:34 +0000 (21:00 +0000)
committerIan Lance Taylor <iant@google.com>
Tue, 26 Sep 2006 21:00:34 +0000 (21:00 +0000)
17 files changed:
gold/Makefile.in
gold/config.in
gold/configure
gold/configure.ac
gold/gold.cc
gold/gold.h
gold/layout.cc
gold/layout.h
gold/object.cc
gold/object.h
gold/output.cc
gold/output.h
gold/po/gold.pot
gold/readsyms.cc
gold/readsyms.h
gold/symtab.cc
gold/symtab.h

index 6dba59c..cb9caa1 100644 (file)
@@ -124,6 +124,7 @@ CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
 CPPFLAGS = @CPPFLAGS@
 CXX = @CXX@
+CXXCPP = @CXXCPP@
 CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
@@ -133,6 +134,7 @@ DEPDIR = @DEPDIR@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
 ECHO_T = @ECHO_T@
+EGREP = @EGREP@
 EXEEXT = @EXEEXT@
 GENCAT = @GENCAT@
 GMSGFMT = @GMSGFMT@
index 05f05ba..8f1b30b 100644 (file)
@@ -4,6 +4,45 @@
    language is requested. */
 #undef ENABLE_NLS
 
+/* Define to 1 if you have the <ext/hash_map> header file. */
+#undef HAVE_EXT_HASH_MAP
+
+/* Define to 1 if you have the <ext/hash_set> header file. */
+#undef HAVE_EXT_HASH_SET
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <tr1/unordered_map> header file. */
+#undef HAVE_TR1_UNORDERED_MAP
+
+/* Define to 1 if you have the <tr1/unordered_set> header file. */
+#undef HAVE_TR1_UNORDERED_SET
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
 /* Name of package */
 #undef PACKAGE
 
@@ -22,5 +61,8 @@
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
 /* Version number of package */
 #undef VERSION
index 96ca974..4bb9743 100755 (executable)
@@ -272,7 +272,44 @@ PACKAGE_STRING=
 PACKAGE_BUGREPORT=
 
 ac_unique_file="gold.cc"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CXXFLAGS MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LIBOBJS LTLIBOBJS'
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CXXFLAGS CXXCPP EGREP MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LIBOBJS LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -737,6 +774,10 @@ ac_env_CXXFLAGS_set=${CXXFLAGS+set}
 ac_env_CXXFLAGS_value=$CXXFLAGS
 ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set}
 ac_cv_env_CXXFLAGS_value=$CXXFLAGS
+ac_env_CXXCPP_set=${CXXCPP+set}
+ac_env_CXXCPP_value=$CXXCPP
+ac_cv_env_CXXCPP_set=${CXXCPP+set}
+ac_cv_env_CXXCPP_value=$CXXCPP
 
 #
 # Report the --help message.
@@ -834,6 +875,7 @@ Some influential environment variables:
               headers in a nonstandard directory <include dir>
   CXX         C++ compiler command
   CXXFLAGS    C++ compiler flags
+  CXXCPP      C++ preprocessor
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
@@ -3888,6 +3930,806 @@ WARN_CXXFLAGS=`echo ${WARN_CFLAGS} | sed -e 's/-Wstrict-prototypes//' -e 's/-Wmi
 LFS_CXXFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
 
 
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6
+if test -z "$CXXCPP"; then
+  if test "${ac_cv_prog_CXXCPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CXXCPP needs to be expanded
+    for CXXCPP in "$CXX -E" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_cxx_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_cxx_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+  CXXCPP=$ac_cv_prog_CXXCPP
+else
+  ac_cv_prog_CXXCPP=$CXXCPP
+fi
+echo "$as_me:$LINENO: result: $CXXCPP" >&5
+echo "${ECHO_T}$CXXCPP" >&6
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_cxx_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_cxx_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+for ac_header in tr1/unordered_set tr1/unordered_map
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_cxx_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in ext/hash_map ext/hash_set
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_cxx_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
 echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5
 echo $ECHO_N "checking whether to enable maintainer-specific portions of Makefiles... $ECHO_C" >&6
     # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
@@ -4649,6 +5491,8 @@ s,@WARN_CFLAGS@,$WARN_CFLAGS,;t t
 s,@NO_WERROR@,$NO_WERROR,;t t
 s,@WARN_CXXFLAGS@,$WARN_CXXFLAGS,;t t
 s,@LFS_CXXFLAGS@,$LFS_CXXFLAGS,;t t
+s,@CXXCPP@,$CXXCPP,;t t
+s,@EGREP@,$EGREP,;t t
 s,@MAINTAINER_MODE_TRUE@,$MAINTAINER_MODE_TRUE,;t t
 s,@MAINTAINER_MODE_FALSE@,$MAINTAINER_MODE_FALSE,;t t
 s,@MAINT@,$MAINT,;t t
index 9e2aba0..b7cdc5e 100644 (file)
@@ -28,6 +28,11 @@ dnl host dependent.  If build == host, we can check getconf LFS_CFLAGS.
 LFS_CXXFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
 AC_SUBST(LFS_CXXFLAGS)
 
+AC_LANG_PUSH(C++)
+AC_CHECK_HEADERS(tr1/unordered_set tr1/unordered_map)
+AC_CHECK_HEADERS(ext/hash_map ext/hash_set)
+AC_LANG_POP(C++)
+
 AM_MAINTAINER_MODE
 
 AC_OUTPUT(Makefile po/Makefile.in:po/Make-in)
index 02e7366..f4642cf 100644 (file)
@@ -12,6 +12,7 @@
 #include "dirsearch.h"
 #include "readsyms.h"
 #include "symtab.h"
+#include "object.h"
 #include "layout.h"
 
 namespace gold
@@ -67,7 +68,7 @@ void
 queue_initial_tasks(const General_options& options,
                    const Dirsearch& search_path,
                    const Command_line::Input_argument_list& inputs,
-                   Workqueue* workqueue, Object_list* input_objects,
+                   Workqueue* workqueue, Input_objects* input_objects,
                    Symbol_table* symtab)
 {
   if (inputs.empty())
@@ -117,7 +118,7 @@ main(int argc, char** argv)
   gold::Workqueue workqueue(command_line.options());
 
   // The list of input objects.
-  Object_list input_objects;
+  Input_objects input_objects;
 
   // The symbol table.
   Symbol_table symtab;
index 757449f..f52d131 100644 (file)
@@ -23,8 +23,9 @@
 # define N_(String) (String)
 #endif
 
-// Figure out how to get a hash set and a hash map.  The fallback is
-// to just use set and map.
+// Figure out how to get a hash set and a hash map.
+
+#if HAVE_TR1_UNORDERED_SET && HAVE_TR1_UNORDERED_MAP
 
 #include <tr1/unordered_set>
 #include <tr1/unordered_map>
 #define Unordered_set std::tr1::unordered_set
 #define Unordered_map std::tr1::unordered_map
 
+#elif HAVE_EXT_HASH_MAP && HAVE_EXT_HASH_SET
+
+#include <ext/hash_map>
+#include <ext/hash_set>
+
+#define Unordered_set __gnu_cxx::hash_set
+#define Unordered_map __gnu_cxx::hash_map
+
+#else
+
+// The fallback is to just use set and map.
+
+#include <set>
+#include <map>
+
+#define Unordered_set std::set
+#define Unordered_map std::map
+
+#endif
+
 namespace gold
 {
 
index 3faec94..1584380 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <cassert>
 #include <cstring>
+#include <algorithm>
 #include <iostream>
 #include <utility>
 
@@ -45,14 +46,34 @@ void
 Layout_task::run(Workqueue*)
 {
   Layout layout(this->options_);
-  for (Object_list::const_iterator p = this->input_objects_->begin();
+  layout.init();
+  for (Input_objects::Object_list::const_iterator p =
+        this->input_objects_->begin();
        p != this->input_objects_->end();
        ++p)
     (*p)->layout(&layout);
+  layout.finalize(this->input_objects_);
 }
 
 // Layout methods.
 
+Layout::Layout(const General_options& options)
+  : options_(options), namepool_(), signatures_(),
+    section_name_map_(), segment_list_(), section_list_(),
+    data_list_()
+{
+}
+
+// Prepare for doing layout.
+
+void
+Layout::init()
+{
+  // Make space for more than enough segments for a typical file.
+  // This is just for efficiency--it's OK if we wind up needing more.
+  segment_list_.reserve(12);
+}
+
 // Hash a key we use to look up an output section mapping.
 
 size_t
@@ -269,8 +290,6 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
              && ((*p)->flags() & elfcpp::PF_W) == (seg_flags & elfcpp::PF_W))
            {
              (*p)->add_output_section(os);
-             if ((*p)->flags() != seg_flags)
-               (*p)->update_flags(seg_flags);
              break;
            }
        }
@@ -297,8 +316,6 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
                      == (seg_flags & elfcpp::PF_W)))
                {
                  (*p)->add_output_section(os);
-                 if ((*p)->flags() != seg_flags)
-                   (*p)->update_flags(seg_flags);
                  break;
                }
            }
@@ -311,11 +328,96 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
              oseg->add_output_section(os);
            }
        }
+
+      // If we see a loadable SHF_TLS section, we create a PT_TLS
+      // segment.
+      if ((flags & elfcpp::SHF_TLS) != 0)
+       {
+         // See if we already have an equivalent PT_TLS segment.
+         for (p = this->segment_list_.begin();
+              p != segment_list_.end();
+              ++p)
+           {
+             if ((*p)->type() == elfcpp::PT_TLS
+                 && (((*p)->flags() & elfcpp::PF_W)
+                     == (seg_flags & elfcpp::PF_W)))
+               {
+                 (*p)->add_output_section(os);
+                 break;
+               }
+           }
+
+         if (p == this->segment_list_.end())
+           {
+             Output_segment* oseg = new Output_segment(elfcpp::PT_TLS,
+                                                       seg_flags);
+             this->segment_list_.push_back(oseg);
+             oseg->add_output_section(os);
+           }
+       }
     }
 
   return os;
 }
 
+// Create the sections for the symbol table.
+
+void
+Layout::create_symtab_sections()
+{
+}
+
+// Finalize the layout.  When this is called, we have created all the
+// output sections and all the output segments which are based on
+// input sections.  We have several things to do, and we have to do
+// them in the right order, so that we get the right results correctly
+// and efficiently.
+
+// 1) Finalize the list of output segments and create the segment
+// table header.
+
+// 2) Finalize the dynamic symbol table and associated sections.
+
+// 3) Determine the final file offset of all the output segments.
+
+// 4) Determine the final file offset of all the SHF_ALLOC output
+// sections.
+
+// 5) Finalize the symbol table: set symbol values to their final
+// value and make a final determination of which symbols are going
+// into the output symbol table.
+
+// 6) Create the symbol table sections and the section name table
+// section.
+
+// 7) Create the section table header.
+
+// 8) Determine the final file offset of all the output sections which
+// are not SHF_ALLOC, including the section table header.
+
+// 9) Finalize the ELF file header.
+
+void
+Layout::finalize(const Input_objects* input_objects)
+{
+  if (input_objects->any_dynamic())
+    {
+      // If there are any dynamic objects in the link, then we need
+      // some additional segments: PT_PHDRS, PT_INTERP, and
+      // PT_DYNAMIC.  We also need to finalize the dynamic symbol
+      // table and create the dynamic hash table.
+      abort();
+    }
+
+  // FIXME: Handle PT_GNU_STACK.
+
+  std::sort(this->segment_list_.begin(), this->segment_list_.end(),
+           Layout::Compare_segments());
+
+  Output_segment_headers* segment_headers;
+  segment_headers = new Output_segment_headers(this->segment_list_);
+}
+
 // The mapping of .gnu.linkonce section names to real section names.
 
 #define MAPPING_INIT(f, t) { f, sizeof(f) - 1, t }
index 77fdfc2..527d2da 100644 (file)
 namespace gold
 {
 
+class Input_objects;
 class Output_section;
+class Output_section_symtab;
 class Output_segment;
+class Output_data;
 
 // This Task handles mapping the input sections to output sections and
 // laying them out in memory.
@@ -28,7 +31,8 @@ class Layout_task : public Task
   // OPTIONS is the command line options, INPUT_OBJECTS is the list of
   // input objects, THIS_BLOCKER is a token which blocks this task
   // from executing until all the input symbols have been read.
-  Layout_task(const General_options& options, const Object_list* input_objects,
+  Layout_task(const General_options& options,
+             const Input_objects* input_objects,
              Task_token* this_blocker)
     : options_(options), input_objects_(input_objects),
       this_blocker_(this_blocker)
@@ -52,7 +56,7 @@ class Layout_task : public Task
   Layout_task& operator=(const Layout_task&);
 
   const General_options& options_;
-  const Object_list* input_objects_;
+  const Input_objects* input_objects_;
   Task_token* this_blocker_;
 };
 
@@ -61,10 +65,11 @@ class Layout_task : public Task
 class Layout
 {
  public:
-  Layout(const General_options& options)
-    : options_(options), namepool_(), signatures_(),
-      section_name_map_(), segment_list_()
-  { }
+  Layout(const General_options& options);
+
+  // Initialize the object.
+  void
+  init();
 
   // Given an input section named NAME with data in SHDR from the
   // object file OBJECT, return the output section where this input
@@ -88,6 +93,22 @@ class Layout
   bool
   add_comdat(const char*, bool group);
 
+  // Finalize the layout after all the input sections have been added.
+  void
+  finalize(const Input_objects*);
+
+  // The list of segments.
+
+  typedef std::vector<Output_segment*> Segment_list;
+
+  // The list of sections not attached to a segment.
+
+  typedef std::list<Output_section*> Section_list;
+
+  // The list of information to write out which is not attached to
+  // either a section or a segment.
+  typedef std::list<Output_data*> Data_list;
+
  private:
   Layout(const Layout&);
   Layout& operator=(const Layout&);
@@ -102,6 +123,19 @@ class Layout
   static const Linkonce_mapping linkonce_mapping[];
   static const int linkonce_mapping_count;
 
+  // Lay out the local symbols from a SHT_SYMTAB section.
+  template<int size, bool big_endian>
+  void
+  add_symtab_locals(Object* object, const elfcpp::Shdr<size, big_endian>&);
+
+  // Create the output sections for the symbol table.
+  void
+  create_symtab_sections();
+
+  // Finalize the symbol table.
+  void
+  finalize_symtab();
+
   // Return whether to include this section in the link.
   template<int size, bool big_endian>
   bool
@@ -153,14 +187,6 @@ class Layout
     { return Layout::segment_precedes(seg1, seg2); }
   };
 
-  // The list of segments.
-
-  typedef std::list<Output_segment*> Segment_list;
-
-  // The list of sections not attached to a segment.
-
-  typedef std::list<Output_section*> Section_list;
-
   // A reference to the options on the command line.
   const General_options& options_;
   // The output section names.
@@ -174,6 +200,9 @@ class Layout
   // The list of output sections which are not attached to any output
   // segment.
   Section_list section_list_;
+  // The list of output data objects which are not attached to any
+  // output section or output segment.
+  Data_list data_list_;
 };
 
 } // End namespace gold.
index 0e00c43..04a31bd 100644 (file)
@@ -136,6 +136,7 @@ Sized_object<size, big_endian>::do_read_symbols()
       Read_symbols_data ret;
       ret.symbols = NULL;
       ret.symbols_size = 0;
+      ret.first_global = 0;
       ret.symbol_names = NULL;
       ret.symbol_names_size = 0;
       return ret;
@@ -149,14 +150,9 @@ Sized_object<size, big_endian>::do_read_symbols()
   elfcpp::Shdr<size, big_endian> symtabshdr(psymtabshdr);
   assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
 
-  // We only need the external symbols.
-  const int sym_size = This::sym_size;
-  off_t locsize = symtabshdr.get_sh_info() * sym_size;
-  off_t extoff = symtabshdr.get_sh_offset() + locsize;
-  off_t extsize = symtabshdr.get_sh_size() - locsize;
-
   // Read the symbol table.
-  File_view* fvsymtab = this->get_lasting_view(extoff, extsize);
+  File_view* fvsymtab = this->get_lasting_view(symtabshdr.get_sh_offset(),
+                                              symtabshdr.get_sh_size());
 
   // Read the section header for the symbol names.
   unsigned int strtab_shnum = symtabshdr.get_sh_link();
@@ -184,7 +180,8 @@ Sized_object<size, big_endian>::do_read_symbols()
 
   Read_symbols_data ret;
   ret.symbols = fvsymtab;
-  ret.symbols_size = extsize;
+  ret.symbols_size = symtabshdr.get_sh_size();
+  ret.first_global = symtabshdr.get_sh_info();
   ret.symbol_names = fvstrtab;
   ret.symbol_names_size = strtabshdr.get_sh_size();
 
@@ -214,14 +211,29 @@ Sized_object<size, big_endian>::do_add_symbols(Symbol_table* symtab,
       gold_exit(false);
     }
 
-  this->symbols_ = new Symbol*[symcount];
-
-  const elfcpp::Sym<size, big_endian>* syms =
-    reinterpret_cast<const elfcpp::Sym<size, big_endian>*>(sd.symbols->data());
   const char* sym_names =
     reinterpret_cast<const char*>(sd.symbol_names->data());
-  symtab->add_from_object(this, syms, symcount, sym_names, 
-                         sd.symbol_names_size,  this->symbols_);
+
+  // We only add the global symbols to the symbol table.
+  if (symcount > sd.first_global)
+    {
+      this->symbols_ = new Symbol*[symcount - sd.first_global];
+
+      const unsigned char* symdata = sd.symbols->data();
+      symdata += sd.first_global * sym_size;
+      const elfcpp::Sym<size, big_endian>* syms =
+       reinterpret_cast<const elfcpp::Sym<size, big_endian>*>(symdata);
+
+      symtab->add_from_object(this, syms, symcount - sd.first_global,
+                             sym_names, sd.symbol_names_size, this->symbols_);
+    }
+
+  // Add the names of the local symbols.  FIXME: We shouldn't do this
+  // if we are stripping symbols.
+  const elfcpp::Sym<size, big_endian>* local_syms =
+    reinterpret_cast<const elfcpp::Sym<size, big_endian>*>(sd.symbols->data());
+  symtab->add_local_symbol_names(this, local_syms, sd.first_global,
+                                sym_names, sd.symbol_names_size);
 
   delete sd.symbols;
   delete sd.symbol_names;
@@ -444,6 +456,16 @@ Sized_object<size, big_endian>::do_layout(Layout* layout)
     }
 }
 
+// Input_objects methods.
+
+void
+Input_objects::add_object(Object* obj)
+{
+  this->object_list_.push_back(obj);
+  if (obj->is_dynamic())
+    this->any_dynamic_ = true;
+}
+
 } // End namespace gold.
 
 namespace
index 0026531..eb3271e 100644 (file)
@@ -25,6 +25,8 @@ struct Read_symbols_data
   File_view* symbols;
   // Size of symbol data in bytes.
   off_t symbols_size;
+  // Index of first global symbol.
+  unsigned int first_global;
   // Symbol names.
   File_view* symbol_names;
   // Size of symbol name data in bytes.
@@ -274,9 +276,43 @@ class Sized_object : public Object
   Symbol** symbols_;
 };
 
-// The type of the list of input objects.
+// A class to manage the list of all objects.
 
-typedef std::list<Object*> Object_list;
+class Input_objects
+{
+ public:
+  Input_objects()
+    : object_list_()
+  { }
+
+  // The type of the list of input objects.
+  typedef std::list<Object*> Object_list;
+
+  // Add an object to the list.
+  void
+  add_object(Object*);
+
+  // Iterate over all objects.
+  Object_list::const_iterator
+  begin() const
+  { return this->object_list_.begin(); }
+
+  Object_list::const_iterator
+  end() const
+  { return this->object_list_.end(); }
+
+  // Return whether we have seen any dynamic objects.
+  bool
+  any_dynamic() const
+  { return this->any_dynamic_; }
+
+ private:
+  Input_objects(const Input_objects&);
+  Input_objects& operator=(const Input_objects&);
+
+  Object_list object_list_;
+  bool any_dynamic_;
+};
 
 // Return an Object appropriate for the input file.  P is BYTES long,
 // and holds the ELF header.
index fcba113..9092301 100644 (file)
@@ -24,6 +24,15 @@ Output_data_const::write(Output_file* output, off_t off)
   output->write(off, data_.data(), data_.size());
 }
 
+// Output_segment_header methods.
+
+void
+Output_segment_headers::write(Output_file*, off_t)
+{
+  // FIXME: Unimplemented.
+  abort();
+}
+
 // Output_section methods.
 
 // Construct an Output_section.  NAME will point into a Stringpool.
@@ -35,7 +44,6 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
     addralign_(0),
     entsize_(0),
     offset_(0),
-    size_(0),
     link_(0),
     info_(0),
     type_(type),
@@ -43,6 +51,10 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
 {
 }
 
+Output_section::~Output_section()
+{
+}
+
 // Add an input section to an Output_section.  We don't keep track of
 // input sections for an Output_section.  Instead, each Object keeps
 // track of the Output_section for each of its input sections.
@@ -60,21 +72,22 @@ Output_section::add_input_section(Object* object, const char* secname,
              static_cast<unsigned long>(addralign), secname);
       gold_exit(false);
     }
-  this->size_ = (this->size_ + addralign - 1) &~ (addralign - 1);
 
   if (addralign > this->addralign_)
     this->addralign_ = addralign;
 
-  off_t ret = this->size_;
-  this->size_ += shdr.get_sh_size();
+  off_t ssize = this->get_size();
+  ssize = (ssize + addralign - 1) &~ (addralign - 1);
 
-  return ret;
+  this->set_size(ssize + shdr.get_sh_size());
+
+  return size;
 }
 
 // Output segment methods.
 
 Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
-  : output_sections_(),
+  : output_data_(),
     vaddr_(0),
     paddr_(0),
     memsz_(0),
@@ -91,6 +104,9 @@ Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
 void
 Output_segment::add_output_section(Output_section* os)
 {
+  // Update the segment flags.
+  this->flags_ |= os->flags() & (elfcpp::PF_R | elfcpp::PF_W | elfcpp::PF_X);
+
   // So that PT_NOTE segments will work correctly, we need to ensure
   // that all SHT_NOTE sections are adjacent.  This will normally
   // happen automatically, because all the SHT_NOTE input sections
@@ -99,22 +115,44 @@ Output_segment::add_output_section(Output_section* os)
   // flags, and thus be in different output sections, but for the
   // different section flags to map into the same segment flags and
   // thus the same output segment.
+
+  // Note that while there may be many input sections in an output
+  // section, there are normally only a few output sections in an
+  // output segment.  This loop is expected to be fast.
+
   if (os->type() == elfcpp::SHT_NOTE)
     {
-      for (Section_list::iterator p = this->output_sections_.begin();
-          p != this->output_sections_.end();
+      for (Layout::Data_list::iterator p = this->output_data_.begin();
+          p != this->output_data_.end();
+          ++p)
+       {
+         if ((*p)->is_section_type(elfcpp::SHT_NOTE))
+           {
+             ++p;
+             this->output_data_.insert(p, os);
+             return;
+           }
+       }
+    }
+
+  // Similarly, so that PT_TLS segments will work, we need to group
+  // SHF_TLS sections.
+  if ((os->flags() & elfcpp::SHF_TLS) != 0)
+    {
+      for (Layout::Data_list::iterator p = this->output_data_.begin();
+          p != this->output_data_.end();
           ++p)
        {
-         if ((*p)->type() == elfcpp::SHT_NOTE)
+         if ((*p)->is_section_flag_set(elfcpp::SHF_TLS))
            {
              ++p;
-             this->output_sections_.insert(p, os);
+             this->output_data_.insert(p, os);
              return;
            }
        }
     }
 
-  this->output_sections_.push_back(os);
+  this->output_data_.push_back(os);
 }
 
 // Output_file methods.
index 943474b..b0d3f80 100644 (file)
@@ -6,6 +6,7 @@
 #include <list>
 
 #include "elfcpp.h"
+#include "layout.h"
 
 namespace gold
 {
@@ -13,8 +14,10 @@ namespace gold
 class Object;
 class Output_file;
 
-// An abtract class for data which has to go into the output file
-// which is not associated with any input section.
+template<int size, bool big_endian>
+class Sized_target;
+
+// An abtract class for data which has to go into the output file.
 
 class Output_data
 {
@@ -26,9 +29,10 @@ class Output_data
   virtual
   ~Output_data();
 
-  // Return the size of the data.
+  // Return the size of the data.  This can't be called "size" since
+  // that interferes with the widely used template parameter name.
   off_t
-  size()
+  get_size()
   { return this->size_; }
 
   // Write the data to the output file at the specified offset.  This
@@ -36,6 +40,17 @@ class Output_data
   virtual void
   write(Output_file*, off_t off) = 0;
 
+  // Return whether this is an Output_section of the specified type.
+  virtual bool
+  is_section_type(elfcpp::Elf_Word)
+  { return false; }
+
+  // Return whether this is an Output_section with the specified flag
+  // set.
+  virtual bool
+  is_section_flag_set(elfcpp::Elf_Xword)
+  { return false; }
+
  protected:
   // Set the size of the data.
   void
@@ -50,7 +65,7 @@ class Output_data
   off_t size_;
 };
 
-// A simple cass of Output_data in which we have constant data to
+// A simple case of Output_data in which we have constant data to
 // output.
 
 class Output_data_const : public Output_data
@@ -64,6 +79,7 @@ class Output_data_const : public Output_data
     : Output_data(len), data_(p, len)
   { }
 
+  // Write the data to the file.
   void
   write(Output_file* output, off_t off);
 
@@ -71,15 +87,74 @@ class Output_data_const : public Output_data
   std::string data_;
 };
 
+// Output the section headers.
+
+class Output_section_headers : public Output_data
+{
+ public:
+  Output_section_headers(const Layout::Segment_list&,
+                        const Layout::Section_list&);
+
+  // Write the data to the file.
+  void
+  write(Output_file*, off_t);
+
+ private:
+  const Layout::Segment_list& segment_list_;
+  const Layout::Section_list& section_list_;
+};
+
+// Output the segment headers.
+
+class Output_segment_headers : public Output_data
+{
+ public:
+  Output_segment_headers(const Layout::Segment_list& segment_list)
+    : segment_list_(segment_list)
+  { }
+
+  // Write the data to the file.
+  void
+  write(Output_file*, off_t);
+
+ private:
+  const Layout::Segment_list& segment_list_;
+};
+
+// Output the ELF file header.
+
+class Output_file_header : public Output_data
+{
+ public:
+  Output_file_header(const General_options&,
+                    const Target*,
+                    const Symbol_table*,
+                    const Output_segment_headers*,
+                    const Output_section_headers*,
+                    const Output_section* shstrtab);
+
+  // Write the data to the file.
+  void
+  write(Output_file*, off_t);
+
+ private:
+  const General_options& options_;
+  const Target* target_;
+  const Symbol_table* symtab_;
+  const Output_segment_headers* program_header_;
+  const Output_section_headers* section_header_;
+  const Output_section* shstrtab_;
+};
+
 // An output section.  We don't expect to have too many output
 // sections, so we don't bother to do a template on the size.
 
-class Output_section
+class Output_section : public Output_data
 {
  public:
   // Create an output section, giving the name, type, and flags.
   Output_section(const char* name, elfcpp::Elf_Word, elfcpp::Elf_Xword);
-  ~Output_section();
+  virtual ~Output_section();
 
   // Add a new input section named NAME with header SHDR from object
   // OBJECT.  Return the offset within the output section.
@@ -103,6 +178,23 @@ class Output_section
   flags() const
   { return this->flags_; }
 
+  // Write the data to the file.  For a typical Output_section, this
+  // does nothing.  We write out the data by looping over all the
+  // input sections.
+  virtual void
+  write(Output_file*, off_t)
+  { }
+
+  // Return whether this is a section of the specified type.
+  bool
+  is_section_type(elfcpp::Elf_Word type)
+  { return this->type_ == type; }
+
+  // Return whether the specified section flag is set.
+  bool
+  is_section_flag_set(elfcpp::Elf_Xword flag)
+  { return (this->flags_ & flag) != 0; }
+
  private:
   // Most of these fields are only valid after layout.
 
@@ -116,8 +208,6 @@ class Output_section
   uint64_t entsize_;
   // The file offset.
   off_t offset_;
-  // The section size.
-  off_t size_;
   // The section link field.
   unsigned int link_;
   // The section info field.
@@ -128,6 +218,16 @@ class Output_section
   elfcpp::Elf_Xword flags_;
 };
 
+// A special Output_section which represents the symbol table
+// (SHT_SYMTAB).
+
+class Output_section_symtab : public Output_section
+{
+ public:
+  Output_section_symtab();
+  ~Output_section_symtab();
+};
+
 // An output segment.  PT_LOAD segments are built from collections of
 // output sections.  Other segments typically point within PT_LOAD
 // segments, and are built directly as needed.
@@ -162,20 +262,15 @@ class Output_segment
   void
   add_output_section(Output_section*);
 
-  // Update the segment flags to be compatible with FLAGS.
-  void
-  update_flags(elfcpp::Elf_Word flags)
-  { this->flags_ |= flags & (elfcpp::PF_R | elfcpp::PF_W | elfcpp::PF_X); }
-
  private:
   Output_segment(const Output_segment&);
   Output_segment& operator=(const Output_segment&);
 
-  typedef std::list<Output_section*> Section_list;
+  typedef std::list<Output_data*> Output_data_list;
 
   // The list of output sections attached to this segment.  This is
   // cleared after layout.
-  Section_list output_sections_;
+  Output_data_list output_data_;
   // The segment virtual address.
   uint64_t vaddr_;
   // The segment physical address.
index e12e01e..e3adeff 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-09-21 13:30-0700\n"
+"POT-Creation-Date: 2006-09-26 13:58-0700\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -51,7 +51,7 @@ msgstr ""
 msgid "%s: cannot open %s: %s"
 msgstr ""
 
-#: gold.cc:74
+#: gold.cc:75
 msgid "no input files"
 msgstr ""
 
@@ -114,88 +114,88 @@ msgstr ""
 msgid "%s: %s: unsupported ELF machine number %d\n"
 msgstr ""
 
-#: object.cc:165
+#: object.cc:161
 #, c-format
 msgid "%s: %s: invalid symbol table name index: %u\n"
 msgstr ""
 
-#: object.cc:175
+#: object.cc:171
 #, c-format
 msgid "%s: %s: symbol table name section has wrong type: %u\n"
 msgstr ""
 
-#: object.cc:212
+#: object.cc:209
 #, c-format
 msgid "%s: %s: size of symbols is not multiple of symbol size\n"
 msgstr ""
 
-#: object.cc:266
+#: object.cc:278
 #, c-format
 msgid "%s: %s: section group %u link %u out of range\n"
 msgstr ""
 
-#: object.cc:277
+#: object.cc:289
 #, c-format
 msgid "%s: %s: section group %u info %u out of range\n"
 msgstr ""
 
-#: object.cc:288
+#: object.cc:300
 #, c-format
 msgid "%s; %s: symtab section %u link %u out of range\n"
 msgstr ""
 
-#: object.cc:306
+#: object.cc:318
 #, c-format
 msgid "%s: %s: symbol %u name offset %u out of range\n"
 msgstr ""
 
-#: object.cc:328
+#: object.cc:340
 #, c-format
 msgid "%s: %s: section %u in section group %u out of range"
 msgstr ""
 
-#: object.cc:407
+#: object.cc:419
 #, c-format
 msgid "%s: %s: bad section name offset for section %u: %lu\n"
 msgstr ""
 
 #. elfcpp::ET_DYN
-#: object.cc:480
+#: object.cc:502
 #, c-format
 msgid "%s: %s: dynamic objects are not yet supported\n"
 msgstr ""
 
-#: object.cc:504 object.cc:557 object.cc:578
+#: object.cc:526 object.cc:579 object.cc:600
 #, c-format
 msgid "%s: %s: ELF file too short\n"
 msgstr ""
 
-#: object.cc:513
+#: object.cc:535
 #, c-format
 msgid "%s: %s: invalid ELF version 0\n"
 msgstr ""
 
-#: object.cc:516
+#: object.cc:538
 #, c-format
 msgid "%s: %s: unsupported ELF version %d\n"
 msgstr ""
 
-#: object.cc:524
+#: object.cc:546
 #, c-format
 msgid "%s: %s: invalid ELF class 0\n"
 msgstr ""
 
-#: object.cc:531
+#: object.cc:553
 #, c-format
 msgid "%s: %s: unsupported ELF class %d\n"
 msgstr ""
 
-#: object.cc:539
+#: object.cc:561
 #, c-format
 msgid "%s: %s: invalid ELF data encoding\n"
 msgstr ""
 
-#: object.cc:546
+#: object.cc:568
 #, c-format
 msgid "%s: %s: unsupported ELF data encoding %d\n"
 msgstr ""
@@ -250,7 +250,7 @@ msgstr ""
 msgid "%s: -%c: %s\n"
 msgstr ""
 
-#: output.cc:58
+#: output.cc:70
 #, c-format
 msgid "%s: %s: invalid alignment %lu for section \"%s\"\n"
 msgstr ""
@@ -270,7 +270,12 @@ msgstr ""
 msgid "%s: %s: mixing 32-bit and 64-bit ELF objects\n"
 msgstr ""
 
-#: symtab.cc:284
+#: symtab.cc:285
+#, c-format
+msgid "%s: %s: bad global symbol name offset %u at %lu\n"
+msgstr ""
+
+#: symtab.cc:342
 #, c-format
-msgid "%s: %s: bad symbol name offset %u at %lu\n"
+msgid "%s: %s: bad local symbol name offset %u at %lu\n"
 msgstr ""
index aa32e36..99fa1b1 100644 (file)
@@ -71,7 +71,7 @@ Read_symbols::run(Workqueue* workqueue)
          Object* obj = make_elf_object(this->input_.name(), input_file, 0,
                                        p, bytes);
 
-         this->input_objects_->push_back(obj);
+         this->input_objects_->add_object(obj);
 
          Read_symbols_data sd = obj->read_symbols();
          workqueue->queue(new Add_symbols(this->symtab_, obj, sd,
index 73d4efe..46d73c8 100644 (file)
@@ -9,6 +9,9 @@
 namespace gold
 {
 
+class Input_objects;
+class Symbol_table;
+
 // This Task is responsible for reading the symbols from an input
 // file.  This also includes reading the relocations so that we can
 // check for any that require a PLT and/or a GOT.  After the data has
@@ -25,7 +28,7 @@ class Read_symbols : public Task
   // associated Add_symbols task from running before the previous one
   // has completed; it will be NULL for the first task.  NEXT_BLOCKER
   // is used to block the next input file from adding symbols.
-  Read_symbols(const General_options& options, Object_list* input_objects,
+  Read_symbols(const General_options& options, Input_objects* input_objects,
               Symbol_table* symtab, const Dirsearch& dirpath,
               const Input_argument& input,
               Task_token* this_blocker, Task_token* next_blocker)
@@ -49,7 +52,7 @@ class Read_symbols : public Task
 
  private:
   const General_options& options_;
-  Object_list* input_objects_;
+  Input_objects* input_objects_;
   Symbol_table* symtab_;
   const Dirsearch& dirpath_;
   const Input_argument& input_;
index 8cf7789..8538c42 100644 (file)
@@ -52,7 +52,7 @@ Sized_symbol<size>::init(const char* name, const char* version, Object* object,
 // Class Symbol_table.
 
 Symbol_table::Symbol_table()
-  : size_(0), table_(), namepool_(), forwarders_()
+  : size_(0), table_(), namepool_(), output_pool_(), forwarders_()
 {
 }
 
@@ -281,7 +281,8 @@ Symbol_table::add_from_object(
       unsigned int st_name = sym.get_st_name();
       if (st_name >= sym_name_size)
        {
-         fprintf(stderr, _("%s: %s: bad symbol name offset %u at %lu\n"),
+         fprintf(stderr,
+                 _("%s: %s: bad global symbol name offset %u at %lu\n"),
                  program_name, object->name().c_str(), st_name,
                  static_cast<unsigned long>(i));
          gold_exit(false);
@@ -320,6 +321,34 @@ Symbol_table::add_from_object(
     }
 }
 
+// Record the names of the local symbols for an object.
+
+template<int size, bool big_endian>
+void
+Symbol_table::add_local_symbol_names(Sized_object<size, big_endian>* object,
+                                    const elfcpp::Sym<size, big_endian>* syms,
+                                    size_t count, const char* sym_names,
+                                    size_t sym_name_size)
+{
+  const unsigned char* p = reinterpret_cast<const unsigned char*>(syms);
+  for (size_t i = 0; i < count; ++i)
+    {
+      elfcpp::Sym<size, big_endian> sym(p);
+
+      unsigned int st_name = sym.get_st_name();
+      if (st_name >= sym_name_size)
+       {
+         fprintf(stderr,
+                 _("%s: %s: bad local symbol name offset %u at %lu\n"),
+                 program_name, object->name().c_str(), st_name,
+                 static_cast<unsigned long>(i));
+         gold_exit(false);
+       }
+
+      this->output_pool_.add(sym_names + st_name);
+    }
+}
+
 // Instantiate the templates we need.  We could use the configure
 // script to restrict this to only the ones needed for implemented
 // targets.
@@ -364,4 +393,40 @@ Symbol_table::add_from_object<64, false>(
     size_t sym_name_size,
     Symbol** sympointers);
 
+template
+void
+Symbol_table::add_local_symbol_names<32, true>(
+    Sized_object<32, true>* object,
+    const elfcpp::Sym<32, true>* syms,
+    size_t count,
+    const char* sym_names,
+    size_t sym_name_size);
+
+template
+void
+Symbol_table::add_local_symbol_names<32, false>(
+    Sized_object<32, false>* object,
+    const elfcpp::Sym<32, false>* syms,
+    size_t count,
+    const char* sym_names,
+    size_t sym_name_size);
+
+template
+void
+Symbol_table::add_local_symbol_names<64, true>(
+    Sized_object<64, true>* object,
+    const elfcpp::Sym<64, true>* syms,
+    size_t count,
+    const char* sym_names,
+    size_t sym_name_size);
+
+template
+void
+Symbol_table::add_local_symbol_names<64, false>(
+    Sized_object<64, false>* object,
+    const elfcpp::Sym<64, false>* syms,
+    size_t count,
+    const char* sym_names,
+    size_t sym_name_size);
+
 } // End namespace gold.
index a7d3423..f5d2a7b 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <string>
 #include <utility>
+#include <cassert>
 
 #include "elfcpp.h"
 #include "stringpool.h"
@@ -20,9 +21,6 @@ class Object;
 template<int size, bool big_endian>
 class Sized_object;
 
-template<int size, bool big_endian>
-class Sized_target;
-
 // The base class of an entry in the symbol table.  The symbol table
 // can have a lot of entries, so we don't want this class to big.
 // Size dependent fields can be found in the template class
@@ -226,11 +224,19 @@ class Symbol_table
   // Return the sized version of a symbol in this table.
   template<int size>
   Sized_symbol<size>*
-  get_sized_symbol(Symbol*);
+  get_sized_symbol(Symbol*) const;
 
   template<int size>
   const Sized_symbol<size>*
-  get_sized_symbol(const Symbol*);
+  get_sized_symbol(const Symbol*) const;
+
+  // Record the names of the local symbols for an object.
+  template<int size, bool big_endian>
+  void
+  add_local_symbol_names(Sized_object<size, big_endian>* object,
+                        const elfcpp::Sym<size, big_endian>* syms,
+                        size_t count, const char* sym_names,
+                        size_t sym_name_size);
 
  private:
   Symbol_table(const Symbol_table&);
@@ -263,6 +269,8 @@ class Symbol_table
   static void
   resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from);
 
+  // The type of the symbol hash table.
+
   typedef std::pair<const char*, const char*> Symbol_table_key;
 
   struct Symbol_table_hash
@@ -283,12 +291,18 @@ class Symbol_table
   // The size of the symbols in the symbol table (32 or 64).
   int size_;
 
-  // The symbol table itself.
+  // The symbol hash table.
   Symbol_table_type table_;
 
-  // A pool of symbol names.
+  // A pool of symbol names.  This is used for all global symbols.
+  // Entries in the hash table point into this pool.
   Stringpool namepool_;
 
+  // A pool of symbol names to go into the output file.  This is used
+  // for all symbols, global and local, but only the names of symbols
+  // which will definitely be output are added to this pool.
+  Stringpool output_pool_;
+
   // Forwarding symbols.
   Unordered_map<Symbol*, Symbol*> forwarders_;
 };
@@ -297,7 +311,7 @@ class Symbol_table
 
 template<int size>
 Sized_symbol<size>*
-Symbol_table::get_sized_symbol(Symbol* sym)
+Symbol_table::get_sized_symbol(Symbol* sym) const
 {
   assert(size == this->get_size());
   return static_cast<Sized_symbol<size>*>(sym);
@@ -305,7 +319,7 @@ Symbol_table::get_sized_symbol(Symbol* sym)
 
 template<int size>
 const Sized_symbol<size>*
-Symbol_table::get_sized_symbol(const Symbol* sym)
+Symbol_table::get_sized_symbol(const Symbol* sym) const
 {
   assert(size == this->get_size());
   return static_cast<const Sized_symbol<size>*>(sym);