diff options
author | Ian Lance Taylor <iant@google.com> | 2006-09-26 21:00:34 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2006-09-26 21:00:34 +0000 |
commit | 54dc6425456514cdc00cdfef5a21a7bdacfcad2d (patch) | |
tree | a0cf4cee57e8ed1f2cd9c938febf6966cfa69920 /gold | |
parent | 41f8ce693c4a04811bf47a8df83c1a376a9f34f4 (diff) | |
download | gdb-54dc6425456514cdc00cdfef5a21a7bdacfcad2d.zip gdb-54dc6425456514cdc00cdfef5a21a7bdacfcad2d.tar.gz gdb-54dc6425456514cdc00cdfef5a21a7bdacfcad2d.tar.bz2 |
More section layout code.
Diffstat (limited to 'gold')
-rw-r--r-- | gold/Makefile.in | 2 | ||||
-rw-r--r-- | gold/config.in | 42 | ||||
-rwxr-xr-x | gold/configure | 846 | ||||
-rw-r--r-- | gold/configure.ac | 5 | ||||
-rw-r--r-- | gold/gold.cc | 5 | ||||
-rw-r--r-- | gold/gold.h | 25 | ||||
-rw-r--r-- | gold/layout.cc | 112 | ||||
-rw-r--r-- | gold/layout.h | 57 | ||||
-rw-r--r-- | gold/object.cc | 50 | ||||
-rw-r--r-- | gold/object.h | 40 | ||||
-rw-r--r-- | gold/output.cc | 60 | ||||
-rw-r--r-- | gold/output.h | 127 | ||||
-rw-r--r-- | gold/po/gold.pot | 49 | ||||
-rw-r--r-- | gold/readsyms.cc | 2 | ||||
-rw-r--r-- | gold/readsyms.h | 7 | ||||
-rw-r--r-- | gold/symtab.cc | 69 | ||||
-rw-r--r-- | gold/symtab.h | 32 |
17 files changed, 1427 insertions, 103 deletions
diff --git a/gold/Makefile.in b/gold/Makefile.in index 6dba59c..cb9caa1 100644 --- a/gold/Makefile.in +++ b/gold/Makefile.in @@ -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@ diff --git a/gold/config.in b/gold/config.in index 05f05ba..8f1b30b 100644 --- a/gold/config.in +++ b/gold/config.in @@ -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 diff --git a/gold/configure b/gold/configure index 96ca974..4bb9743 100755 --- a/gold/configure +++ b/gold/configure @@ -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 diff --git a/gold/configure.ac b/gold/configure.ac index 9e2aba0..b7cdc5e 100644 --- a/gold/configure.ac +++ b/gold/configure.ac @@ -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) diff --git a/gold/gold.cc b/gold/gold.cc index 02e7366..f4642cf 100644 --- a/gold/gold.cc +++ b/gold/gold.cc @@ -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; diff --git a/gold/gold.h b/gold/gold.h index 757449f..f52d131 100644 --- a/gold/gold.h +++ b/gold/gold.h @@ -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> @@ -34,6 +35,26 @@ #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 { diff --git a/gold/layout.cc b/gold/layout.cc index 3faec94..1584380 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -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 } diff --git a/gold/layout.h b/gold/layout.h index 77fdfc2..527d2da 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -16,8 +16,11 @@ 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. diff --git a/gold/object.cc b/gold/object.cc index 0e00c43..04a31bd 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -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 diff --git a/gold/object.h b/gold/object.h index 0026531..eb3271e 100644 --- a/gold/object.h +++ b/gold/object.h @@ -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. diff --git a/gold/output.cc b/gold/output.cc index fcba113..9092301 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -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. diff --git a/gold/output.h b/gold/output.h index 943474b..b0d3f80 100644 --- a/gold/output.h +++ b/gold/output.h @@ -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. diff --git a/gold/po/gold.pot b/gold/po/gold.pot index e12e01e..e3adeff 100644 --- a/gold/po/gold.pot +++ b/gold/po/gold.pot @@ -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 "" diff --git a/gold/readsyms.cc b/gold/readsyms.cc index aa32e36..99fa1b1 100644 --- a/gold/readsyms.cc +++ b/gold/readsyms.cc @@ -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, diff --git a/gold/readsyms.h b/gold/readsyms.h index 73d4efe..46d73c8 100644 --- a/gold/readsyms.h +++ b/gold/readsyms.h @@ -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_; diff --git a/gold/symtab.cc b/gold/symtab.cc index 8cf7789..8538c42 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -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. diff --git a/gold/symtab.h b/gold/symtab.h index a7d3423..f5d2a7b 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -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); |