From 9a0910c33e1a6962d475ee0a994fd1f5e446a888 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 30 Nov 2007 00:35:27 +0000 Subject: From Craig Silverstein: Add support for compressing .debug_str section. --- gold/Makefile.am | 2 + gold/Makefile.in | 7 +- gold/compressed_output.cc | 267 ++++++++++++ gold/compressed_output.h | 137 ++++++ gold/config.in | 3 + gold/configure | 1028 +++++++++++++++++++++++++++++++++----------- gold/configure.ac | 3 + gold/layout.cc | 46 +- gold/layout.h | 20 +- gold/merge.cc | 21 +- gold/merge.h | 16 + gold/options.cc | 12 + gold/options.h | 36 +- gold/output.cc | 112 ++++- gold/output.h | 45 +- gold/po/POTFILES.in | 2 + gold/po/gold.pot | 246 ++++++----- gold/stringpool.cc | 42 +- gold/stringpool.h | 10 + gold/testsuite/Makefile.in | 1 + 20 files changed, 1639 insertions(+), 417 deletions(-) create mode 100644 gold/compressed_output.cc create mode 100644 gold/compressed_output.h (limited to 'gold') diff --git a/gold/Makefile.am b/gold/Makefile.am index de9be20..84c39b9 100644 --- a/gold/Makefile.am +++ b/gold/Makefile.am @@ -30,6 +30,7 @@ noinst_LIBRARIES = libgold.a CCFILES = \ archive.cc \ common.cc \ + compressed_output.cc \ defstd.cc \ dirsearch.cc \ dynobj.cc \ @@ -59,6 +60,7 @@ CCFILES = \ HFILES = \ archive.h \ common.h \ + compressed_output.h \ defstd.h \ dirsearch.h \ dynobj.h \ diff --git a/gold/Makefile.in b/gold/Makefile.in index fd981d6..cae5524 100644 --- a/gold/Makefile.in +++ b/gold/Makefile.in @@ -70,7 +70,8 @@ AR = ar ARFLAGS = cru libgold_a_AR = $(AR) $(ARFLAGS) libgold_a_LIBADD = -am__objects_1 = archive.$(OBJEXT) common.$(OBJEXT) defstd.$(OBJEXT) \ +am__objects_1 = archive.$(OBJEXT) common.$(OBJEXT) \ + compressed_output.$(OBJEXT) defstd.$(OBJEXT) \ dirsearch.$(OBJEXT) dynobj.$(OBJEXT) dwarf_reader.$(OBJEXT) \ ehframe.$(OBJEXT) errors.$(OBJEXT) fileread.$(OBJEXT) \ gold.$(OBJEXT) gold-threads.$(OBJEXT) layout.$(OBJEXT) \ @@ -152,6 +153,7 @@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ +CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ @@ -285,6 +287,7 @@ noinst_LIBRARIES = libgold.a CCFILES = \ archive.cc \ common.cc \ + compressed_output.cc \ defstd.cc \ dirsearch.cc \ dynobj.cc \ @@ -314,6 +317,7 @@ CCFILES = \ HFILES = \ archive.h \ common.h \ + compressed_output.h \ defstd.h \ dirsearch.h \ dynobj.h \ @@ -465,6 +469,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pread.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/archive.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compressed_output.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defstd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirsearch.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_reader.Po@am__quote@ diff --git a/gold/compressed_output.cc b/gold/compressed_output.cc new file mode 100644 index 0000000..1006ac8 --- /dev/null +++ b/gold/compressed_output.cc @@ -0,0 +1,267 @@ +// compressed_output.cc -- manage compressed output sections for gold + +// Copyright 2007 Free Software Foundation, Inc. +// Written by Ian Lance Taylor . + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" + +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "compressed_output.h" +#include "parameters.h" + +namespace gold +{ + +// Compress UNCOMPRESSED_DATA of size UNCOMPRESSED_SIZE. Returns true +// if it successfully compressed, false if it failed for any reason +// (including not having zlib support in the library). If it returns +// true, it allocates memory for the compressed data using new, and +// sets *COMPRESSED_DATA and *COMPRESSED_SIZE to appropriate values. + +static bool +zlib_compress(const char* uncompressed_data, unsigned long uncompressed_size, + char** compressed_data, unsigned long* compressed_size) +{ +#ifndef HAVE_ZLIB_H + return false; +#else + *compressed_size = uncompressed_size + uncompressed_size / 1000 + 128; + *compressed_data = new char[*compressed_size]; + + int compress_level; + if (parameters->optimization_level() >= 1) + compress_level = 9; + else + compress_level = 1; + + int rc = compress2(reinterpret_cast(*compressed_data), + compressed_size, + reinterpret_cast(uncompressed_data), + uncompressed_size, + compress_level); + if (rc == Z_OK) + return true; + else + { + delete[] *compressed_data; + *compressed_data = NULL; + return false; + } +#endif // #ifdef HAVE_ZLIB_H +} + +// After compressing an output section, we rename it from foo to +// foo.zlib.nnnn, where nnnn is the uncompressed size of the section. + +static std::string +zlib_compressed_suffix(unsigned long uncompressed_size) +{ + char size_string[64]; + snprintf(size_string, sizeof(size_string), "%lu", uncompressed_size); + return std::string(".zlib.") + size_string; +} + +// Class Output_compressed_section_data. + +// Add an input section. In this case, we just keep track of the sections. + +bool +Output_compressed_section_data::do_add_input_section(Relobj* obj, + unsigned int shndx) +{ + this->objects_.push_back(Object_entry(obj, shndx)); + return true; +} + +// Set the final data size of a compressed section. This is where +// we actually compress the section data. + +void +Output_compressed_section_data::set_final_data_size() +{ + // FIXME: assert that relocations have already been applied. + + off_t uncompressed_size = 0; + for (std::vector::iterator it = this->objects_.begin(); + it != this->objects_.end(); + ++it) + { + it->contents + = it->object->section_contents(it->shndx, &it->length, false); + uncompressed_size += it->length; + } + + // (Try to) compress the data. + unsigned long compressed_size; + char* uncompressed_data = new char[uncompressed_size]; + off_t pos = 0; + for (std::vector::const_iterator it = this->objects_.begin(); + it != this->objects_.end(); + ++it) + { + memcpy(uncompressed_data + pos, + reinterpret_cast(it->contents), + it->length); + pos += it->length; + } + + bool success = false; + if (options_.zlib_compress_debug_sections()) + success = zlib_compress(uncompressed_data, uncompressed_size, + &this->data_, &compressed_size); + if (success) + { + delete[] uncompressed_data; + this->set_data_size(compressed_size); + this->new_section_name_ = zlib_compressed_suffix(uncompressed_size); + } + else + { + gold_warning(_("Not compressing section data: zlib error")); + gold_assert(this->data_ == NULL); + this->data_ = uncompressed_data; + this->set_data_size(uncompressed_size); + } +} + +// Change the name of the output section to reflect it's compressed. +// The layout routines call into this right before finalizing the +// shstrtab. + +const char* +Output_compressed_section_data::do_modified_output_section_name( + const char* name) +{ + // This mean we never compressed the data. + if (this->new_section_name_.empty()) + return NULL; + this->new_section_name_ = std::string(name) + this->new_section_name_; + return this->new_section_name_.c_str(); +} + +// Write out a compressed section. If we couldn't compress, we just +// write it out as normal, uncompressed data. + +void +Output_compressed_section_data::do_write(Output_file* of) +{ + unsigned char* uview = of->get_output_view(this->offset(), + this->data_size()); + char* view = reinterpret_cast(uview); + memcpy(view, this->data_, this->data_size()); + of->write_output_view(this->offset(), this->data_size(), uview); +} + +// Class Output_compressed_string. + +// Add an input section. We don't do anything special here. + +template +bool +Output_compressed_string::do_add_input_section(Relobj* object, + unsigned int shndx) +{ + return Output_merge_string::do_add_input_section(object, shndx); +} + +// Set the final data size of a compressed section. This is where +// we actually compress the section data. + +template +void +Output_compressed_string::set_final_data_size() +{ + // First let the superclass finalize all its data, then write it to + // a buffer. + unsigned long uncompressed_size = this->finalize_merged_data(); + char* uncompressed_data = new char[uncompressed_size]; + this->stringpool_to_buffer(uncompressed_data, uncompressed_size); + + // (Try to) compress the data. + unsigned long compressed_size; + if (options_.zlib_compress_debug_sections() + && zlib_compress(uncompressed_data, uncompressed_size, + &this->compressed_data_, &compressed_size)) + { + this->set_data_size(compressed_size); + // Save some memory. + this->clear_stringpool(); + // We will be renaming the section to name.zlib.uncompressed_size. + this->new_section_name_ = zlib_compressed_suffix(uncompressed_size); + } + else + { + this->compressed_data_ = NULL; + this->set_data_size(uncompressed_size); + } + + delete[] uncompressed_data; +} + +// Change the name of the output section to reflect it's compressed. +// The layout routines call into this right before finalizing the +// shstrtab. + +template +const char* +Output_compressed_string::do_modified_output_section_name( + const char* name) +{ + // This mean we never compressed the data + if (this->new_section_name_.empty()) + return NULL; + this->new_section_name_ = std::string(name) + this->new_section_name_; + return this->new_section_name_.c_str(); +} + +// Write out a compressed string section. If we couldn't compress, +// we just write out the normal string section. + +template +void +Output_compressed_string::do_write(Output_file* of) +{ + if (this->compressed_data_ == NULL) + Output_merge_string::do_write(of); + else + { + unsigned char* uview = of->get_output_view(this->offset(), + this->data_size()); + char* view = reinterpret_cast(uview); + memcpy(view, this->compressed_data_, this->data_size()); + of->write_output_view(this->offset(), this->data_size(), uview); + } +} + +// Instantiate the templates we need. + +template +class Output_compressed_string; + +template +class Output_compressed_string; + +template +class Output_compressed_string; + +} // End namespace gold. diff --git a/gold/compressed_output.h b/gold/compressed_output.h new file mode 100644 index 0000000..589dacc --- /dev/null +++ b/gold/compressed_output.h @@ -0,0 +1,137 @@ +// compressed_output.h -- compressed output sections for gold -*- C++ -*- + +// Copyright 2007 Free Software Foundation, Inc. +// Written by Ian Lance Taylor . + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// We support compressing .debug_* sections on output. (And, +// potentially one day, other sections.) This is a form of +// relaxation. This file adds support for merging and emitting the +// compressed sections. + +#ifndef GOLD_COMPRESSED_OUTPUT_H +#define GOLD_COMPRESSED_OUTPUT_H + +#include +#include + +#include "output.h" +#include "merge.h" + +namespace gold +{ + +class General_options; + +// This is used for compressing a section before emitting it in the +// output file. This only works for unloaded sections, since it +// assumes the final section contents are available at +// set_final_data_size() time. For loaded sections (those that end up +// in segments), this is not true; relocations are applied after +// set_final_data_size() is called. However, for unloaded sections, +// we can -- and do -- postpone calling finalize_data_size() until +// after relocations are applies. + +class Output_compressed_section_data : public Output_section_data +{ + public: + Output_compressed_section_data(uint64_t addralign, + const General_options& options) + : Output_section_data(addralign), options_(options), data_(NULL) + { } + + protected: + // Add an input section. + bool + do_add_input_section(Relobj* object, unsigned int shndx); + + // Set the final data size. + void + set_final_data_size(); + + // Change the name of the output section to reflect it's compressed. + const char* + do_modified_output_section_name(const char* name); + + // Write the data to the file. + void + do_write(Output_file*); + + private: + struct Object_entry + { + Relobj* object; + unsigned int shndx; + const unsigned char* contents; + off_t length; + + Object_entry(Relobj* o, unsigned int s) + : object(o), shndx(s), contents(NULL), length(0) + { } + }; + + const General_options& options_; + std::vector objects_; + char* data_; + std::string new_section_name_; +}; + +// This is a special case for when the output section is a string +// section and does not have any relocations to apply to it. + +template +class Output_compressed_string : public Output_merge_string +{ + public: + Output_compressed_string(uint64_t addralign, + const General_options& options) + : Output_merge_string(addralign), + options_(options), compressed_data_(NULL) + { } + + ~Output_compressed_string() + { delete[] compressed_data_; } + + protected: + // Add an input section. + bool + do_add_input_section(Relobj* object, unsigned int shndx); + + // Set the final data size. Also compresses the buffer. + void + set_final_data_size(); + + // Change the name of the output section to reflect it's compressed. + const char* + do_modified_output_section_name(const char* name); + + // Write the data to the file. + void + do_write(Output_file*); + + private: + const General_options& options_; + char* compressed_data_; + // This is just a buffer to store the section name in "permanent" storage. + std::string new_section_name_; +}; + +} // End namespace gold. + +#endif // !defined(GOLD_COMPRESSED_OUTPUT_H) diff --git a/gold/config.in b/gold/config.in index 7550224..9c0db95 100644 --- a/gold/config.in +++ b/gold/config.in @@ -67,6 +67,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the header file. */ +#undef HAVE_ZLIB_H + /* Name of package */ #undef PACKAGE diff --git a/gold/configure b/gold/configure index 7648c2c..66e6167 100755 --- a/gold/configure +++ b/gold/configure @@ -309,7 +309,7 @@ ac_includes_default="\ # include #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 THREADS_TRUE THREADS_FALSE TARGETOBJS 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 YACC RANLIB ac_ct_RANLIB LN_S USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE NATIVE_LINKER_TRUE NATIVE_LINKER_FALSE GCC_TRUE GCC_FALSE FN_PTRS_IN_SO_WITHOUT_PIC_TRUE FN_PTRS_IN_SO_WITHOUT_PIC_FALSE TLS_TRUE TLS_FALSE STATIC_TLS_TRUE STATIC_TLS_FALSE WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CXXFLAGS LIBOBJS CXXCPP EGREP MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LTLIBOBJS' +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 THREADS_TRUE THREADS_FALSE TARGETOBJS 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 YACC RANLIB ac_ct_RANLIB LN_S USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE NATIVE_LINKER_TRUE NATIVE_LINKER_FALSE GCC_TRUE GCC_FALSE FN_PTRS_IN_SO_WITHOUT_PIC_TRUE FN_PTRS_IN_SO_WITHOUT_PIC_FALSE TLS_TRUE TLS_FALSE STATIC_TLS_TRUE STATIC_TLS_FALSE WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CXXFLAGS LIBOBJS CPP EGREP CXXCPP MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -774,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_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP ac_env_CXXCPP_set=${CXXCPP+set} ac_env_CXXCPP_value=$CXXCPP ac_cv_env_CXXCPP_set=${CXXCPP+set} @@ -884,6 +888,7 @@ Some influential environment variables: headers in a nonstandard directory CXX C++ compiler command CXXFLAGS C++ compiler flags + CPP C preprocessor CXXCPP C++ preprocessor Use these variables to override the choices made by `configure' or to help @@ -4755,6 +4760,771 @@ done +# Link in zlib if we can. This allows us to write compressed sections. +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 how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # 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 +#else +# include +#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_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_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 +_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_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_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_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # 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 +#else +# include +#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_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_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 +_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_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_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 \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +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 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 +#include +#include +#include + +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_c_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 + +_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 + +_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 +#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_c_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 + + +echo "$as_me:$LINENO: checking for library containing zlibVersion" >&5 +echo $ECHO_N "checking for library containing zlibVersion... $ECHO_C" >&6 +if test "${ac_cv_search_zlibVersion+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_zlibVersion=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char zlibVersion (); +int +main () +{ +zlibVersion (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 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_c_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_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 + ac_cv_search_zlibVersion="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_zlibVersion" = no; then + for ac_lib in z; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char zlibVersion (); +int +main () +{ +zlibVersion (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 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_c_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_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 + ac_cv_search_zlibVersion="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_zlibVersion" >&5 +echo "${ECHO_T}$ac_cv_search_zlibVersion" >&6 +if test "$ac_cv_search_zlibVersion" != no; then + test "$ac_cv_search_zlibVersion" = "none required" || LIBS="$ac_cv_search_zlibVersion $LIBS" + +for ac_header in zlib.h +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_c_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_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_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_c_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 gold 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 + +fi + + ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -4994,259 +5764,6 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex 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 -#include -#include -#include - -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 - -_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 - -_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 -#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 @@ -6534,8 +7051,9 @@ s,@NO_WERROR@,$NO_WERROR,;t t s,@WARN_CXXFLAGS@,$WARN_CXXFLAGS,;t t s,@LFS_CXXFLAGS@,$LFS_CXXFLAGS,;t t s,@LIBOBJS@,$LIBOBJS,;t t -s,@CXXCPP@,$CXXCPP,;t t +s,@CPP@,$CPP,;t t s,@EGREP@,$EGREP,;t t +s,@CXXCPP@,$CXXCPP,;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 e230b5f..ea4fd67 100644 --- a/gold/configure.ac +++ b/gold/configure.ac @@ -202,6 +202,9 @@ AC_SUBST(LFS_CXXFLAGS) AC_REPLACE_FUNCS(pread) +# Link in zlib if we can. This allows us to write compressed sections. +AC_SEARCH_LIBS(zlibVersion, z, [AC_CHECK_HEADERS(zlib.h)]) + AC_LANG_PUSH(C++) AC_CHECK_HEADERS(tr1/unordered_set tr1/unordered_map) diff --git a/gold/layout.cc b/gold/layout.cc index d95aea4..f7c1e40 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -393,7 +393,7 @@ Output_section* Layout::make_output_section(const char* name, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags) { - Output_section* os = new Output_section(name, type, flags); + Output_section* os = new Output_section(this->options_, name, type, flags); this->section_list_.push_back(os); if ((flags & elfcpp::SHF_ALLOC) == 0) @@ -710,7 +710,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab) // Set the file offsets of all the non-data sections which don't // have to wait for the input sections. - off = this->set_section_offsets(off, false); + off = this->set_section_offsets(off, BEFORE_INPUT_SECTIONS_PASS); // Now that all sections have been created, set the section indexes. shndx = this->set_section_indexes(shndx); @@ -1059,7 +1059,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, // segment. off_t -Layout::set_section_offsets(off_t off, bool after_input_sections) +Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass) { for (Section_list::iterator p = this->unattached_section_list_.begin(); p != this->unattached_section_list_.end(); @@ -1069,8 +1069,17 @@ Layout::set_section_offsets(off_t off, bool after_input_sections) if (*p == this->symtab_section_) continue; - if ((*p)->after_input_sections() != after_input_sections) - continue; + if (pass == BEFORE_INPUT_SECTIONS_PASS + && (*p)->after_input_sections()) + continue; + else if (pass == AFTER_INPUT_SECTIONS_PASS + && (!(*p)->after_input_sections() + || (*p)->type() == elfcpp::SHT_STRTAB)) + continue; + else if (pass == STRTAB_AFTER_INPUT_SECTIONS_PASS + && (!(*p)->after_input_sections() + || (*p)->type() != elfcpp::SHT_STRTAB)) + continue; off = align_address(off, (*p)->addralign()); (*p)->set_file_offset(off); @@ -1080,6 +1089,19 @@ Layout::set_section_offsets(off_t off, bool after_input_sections) return off; } +// Allow any section not associated with a segment to change its +// output section name at the last minute. + +void +Layout::modify_section_names() +{ + for (Section_list::iterator p = this->unattached_section_list_.begin(); + p != this->unattached_section_list_.end(); + ++p) + if ((*p)->maybe_modify_output_section_name()) + this->namepool_.add((*p)->name(), true, NULL); +} + // Set the section indexes of all the sections not associated with a // segment. @@ -1883,9 +1905,19 @@ void Layout::write_sections_after_input_sections(Output_file* of) { // Determine the final section offsets, and thus the final output - // file size. + // file size. Note we finalize the .shstrab last, to allow the + // after_input_section sections to modify their section-names before + // writing. off_t off = this->output_file_size_; - off = this->set_section_offsets(off, true); + off = this->set_section_offsets(off, AFTER_INPUT_SECTIONS_PASS); + + // Determine the final section names as well (at least, for sections + // that we haven't written yet). + this->modify_section_names(); + + // Now that we've finalized the names, we can finalize the shstrab. + off = this->set_section_offsets(off, STRTAB_AFTER_INPUT_SECTIONS_PASS); + if (off > this->output_file_size_) { of->resize(off); diff --git a/gold/layout.h b/gold/layout.h index 0659d1b..cff29ed 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -342,9 +342,25 @@ class Layout set_segment_offsets(const Target*, Output_segment*, unsigned int* pshndx); // Set the final file offsets of all the sections not associated - // with a segment. + // with a segment. We set section offsets in three passes: the + // first handles all allocated sections, the second sections that + // can be handled after input-sections are processed, and the last + // the late-bound STRTAB sections (probably only shstrtab, which is + // the one we care about because it holds section names). + enum Section_offset_pass + { + BEFORE_INPUT_SECTIONS_PASS, + AFTER_INPUT_SECTIONS_PASS, + STRTAB_AFTER_INPUT_SECTIONS_PASS + }; off_t - set_section_offsets(off_t, bool after_input_sections); + set_section_offsets(off_t, Section_offset_pass pass); + + // We also allow any section not associated with a segment to change + // its output section name at the last minute. Compressed sections + // use this to embed compression info in their name. + void + modify_section_names(); // Set the final section indexes of all the sections not associated // with a segment. Returns the next unused index. diff --git a/gold/merge.cc b/gold/merge.cc index 726a972..215bc34 100644 --- a/gold/merge.cc +++ b/gold/merge.cc @@ -496,13 +496,12 @@ Output_merge_string::do_add_input_section(Relobj* object, return true; } -// Set the final data size of a merged string section. This is where -// we finalize the mappings from the input sections to the output -// section. +// Finalize the mappings from the input sections to the output +// section, and return the final data size. template -void -Output_merge_string::set_final_data_size() +off_t +Output_merge_string::finalize_merged_data() { this->stringpool_.set_string_offsets(); @@ -513,10 +512,18 @@ Output_merge_string::set_final_data_size() this->add_mapping(p->object, p->shndx, p->offset, p->length, this->stringpool_.get_offset(p->string)); - this->set_data_size(this->stringpool_.get_strtab_size()); - // Save some memory. this->merged_strings_.clear(); + + return this->stringpool_.get_strtab_size(); +} + +template +void +Output_merge_string::set_final_data_size() +{ + const off_t final_data_size = this->finalize_merged_data(); + this->set_data_size(final_data_size); } // Write out a merged string section. diff --git a/gold/merge.h b/gold/merge.h index 70fe6b7..a28ff42 100644 --- a/gold/merge.h +++ b/gold/merge.h @@ -209,10 +209,16 @@ class Output_merge_string : public Output_merge_base this->stringpool_.set_no_zero_null(); } + protected: // Add an input section. bool do_add_input_section(Relobj* object, unsigned int shndx); + // Do all the final processing after the input sections are read in. + // Returns the final data size. + off_t + finalize_merged_data(); + // Set the final data size. void set_final_data_size(); @@ -221,6 +227,16 @@ class Output_merge_string : public Output_merge_base void do_write(Output_file*); + // Writes the stringpool to a buffer. + void + stringpool_to_buffer(char* buffer, size_t buffer_size) + { this->stringpool_.write_to_buffer(buffer, buffer_size); } + + // Clears all the data in the stringpool, to save on memory. + void + clear_stringpool() + { stringpool_.clear(); } + private: // As we see input sections, we build a mapping from object, section // index and offset to strings. diff --git a/gold/options.cc b/gold/options.cc index fb79901..f5fc8da 100644 --- a/gold/options.cc +++ b/gold/options.cc @@ -376,6 +376,17 @@ options::Command_line_options::options[] = &Position_dependent_options::set_static_search), GENERAL_NOARG('\0', "Bsymbolic", N_("Bind defined symbols locally"), NULL, ONE_DASH, &General_options::set_symbolic), +#ifdef HAVE_ZLIB_H +# define ZLIB_STR ",zlib" +#else +# define ZLIB_STR "" +#endif + GENERAL_ARG('\0', "compress-debug-sections", + N_("Compress .debug_* sections in the output file " + "(default is none)"), + N_("--compress-debug-sections=[none" ZLIB_STR "]"), + TWO_DASHES, + &General_options::set_compress_debug_symbols), GENERAL_NOARG('\0', "demangle", N_("Demangle C++ symbols in log messages"), NULL, TWO_DASHES, &General_options::set_demangle), GENERAL_NOARG('\0', "no-demangle", @@ -525,6 +536,7 @@ General_options::General_options() strip_(STRIP_NONE), allow_shlib_undefined_(false), symbolic_(false), + compress_debug_sections_(NO_COMPRESSION), detect_odr_violations_(false), create_eh_frame_hdr_(false), rpath_(), diff --git a/gold/options.h b/gold/options.h index c7b08e8..b327aa9 100644 --- a/gold/options.h +++ b/gold/options.h @@ -150,8 +150,8 @@ class General_options strip_debug() const { return this->strip_ == STRIP_ALL || this->strip_ == STRIP_DEBUG; } - // -Sgdb: strip only debugging information that's not used by - // gdb (at least, for gdb versions <= 6.7). + // --strip-debug-gdb: strip only debugging information that's not + // used by gdb (at least, for gdb versions <= 6.7). bool strip_debug_gdb() const { return this->strip_debug() || this->strip_ == STRIP_DEBUG_UNUSED_BY_GDB; } @@ -167,6 +167,17 @@ class General_options symbolic() const { return this->symbolic_; } + // --compress-debug-sections: compress .debug_* sections in the + // output file using the given compression method. This is useful + // when the tools (such as gdb) support compressed sections. + bool + compress_debug_sections() const + { return this->compress_debug_sections_ != NO_COMPRESSION; } + + bool + zlib_compress_debug_sections() const + { return this->compress_debug_sections_ == ZLIB_COMPRESSION; } + // --demangle: demangle C++ symbols in our log messages. bool demangle() const @@ -288,6 +299,13 @@ class General_options EXECSTACK_NO }; + // What compression method to use + enum CompressionMethod + { + NO_COMPRESSION, + ZLIB_COMPRESSION, + }; + void set_export_dynamic() { this->export_dynamic_ = true; } @@ -342,6 +360,19 @@ class General_options set_symbolic() { this->symbolic_ = true; } + void set_compress_debug_symbols(const char* arg) + { + if (strcmp(arg, "none") == 0) + this->compress_debug_sections_ = NO_COMPRESSION; +#ifdef HAVE_ZLIB_H + else if (strcmp(arg, "zlib") == 0) + this->compress_debug_sections_ = ZLIB_COMPRESSION; +#endif + else + gold_fatal(_("Unsupported argument to --compress-debug-symbols: %s"), + arg); + } + void set_demangle() { this->demangle_ = true; } @@ -476,6 +507,7 @@ class General_options Strip strip_; bool allow_shlib_undefined_; bool symbolic_; + CompressionMethod compress_debug_sections_; bool demangle_; bool detect_odr_violations_; bool create_eh_frame_hdr_; diff --git a/gold/output.cc b/gold/output.cc index d89c72a..351c21d 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -32,6 +32,7 @@ #include "libiberty.h" // for unlink_if_ordinary() #include "parameters.h" +#include "compressed_output.h" #include "object.h" #include "symtab.h" #include "reloc.h" @@ -1033,9 +1034,11 @@ Output_section::Input_section::write(Output_file* of) // Construct an Output_section. NAME will point into a Stringpool. -Output_section::Output_section(const char* name, elfcpp::Elf_Word type, +Output_section::Output_section(const General_options& options, + const char* name, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags) - : name_(name), + : options_(options), + name_(name), addralign_(0), entsize_(0), link_section_(NULL), @@ -1079,6 +1082,22 @@ Output_section::set_entsize(uint64_t v) gold_assert(this->entsize_ == v); } +// Sometimes we compress sections. This is typically done for +// sections that are not part of normal program execution (such as +// .debug_* sections), and where the readers of these sections know +// how to deal with compressed sections. (To make it easier for them, +// we will rename the ouput section in such cases from .foo to +// .foo.zlib.nnnn, where nnnn is the uncompressed size.) This routine +// doesn't say for certain whether we'll compress -- it depends on +// commandline options as well -- just whether this section is a +// candidate for compression. + +static bool +is_compressible_section(const char* secname) +{ + return (strncmp(secname, ".debug", sizeof(".debug") - 1) == 0); +} + // Add the input section SHNDX, with header SHDR, named SECNAME, in // OBJECT, to the Output_section. RELOC_SHNDX is the index of a // relocation section which applies to this section, or 0 if none, or @@ -1126,7 +1145,8 @@ Output_section::add_input_section(Sized_relobj* object, && reloc_shndx == 0) { if (this->add_merge_input_section(object, shndx, sh_flags, - entsize, addralign)) + entsize, addralign, + is_compressible_section(secname))) { // Tell the relocation routines that they need to call the // output_offset method to determine the final address. @@ -1213,7 +1233,8 @@ Output_section::add_output_merge_section(Output_section_data* posd, bool Output_section::add_merge_input_section(Relobj* object, unsigned int shndx, uint64_t flags, uint64_t entsize, - uint64_t addralign) + uint64_t addralign, + bool is_compressible_section) { bool is_string = (flags & elfcpp::SHF_STRINGS) != 0; @@ -1227,30 +1248,56 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx, p != this->input_sections_.end(); ++p) if (p->is_merge_section(is_string, entsize, addralign)) - break; + { + p->add_input_section(object, shndx); + return true; + } // We handle the actual constant merging in Output_merge_data or // Output_merge_string_data. - if (p != this->input_sections_.end()) - p->add_input_section(object, shndx); + Output_section_data* posd; + if (!is_string) + posd = new Output_merge_data(entsize, addralign); + else if (is_compressible_section && options_.compress_debug_sections()) + { + switch (entsize) + { + case 1: + posd = new Output_compressed_string(addralign, this->options_); + break; + case 2: + posd = new Output_compressed_string(addralign, + this->options_); + break; + case 4: + posd = new Output_compressed_string(addralign, + this->options_); + break; + default: + return false; + } + } else { - Output_section_data* posd; - if (!is_string) - posd = new Output_merge_data(entsize, addralign); - else if (entsize == 1) - posd = new Output_merge_string(addralign); - else if (entsize == 2) - posd = new Output_merge_string(addralign); - else if (entsize == 4) - posd = new Output_merge_string(addralign); - else - return false; - - this->add_output_merge_section(posd, is_string, entsize); - posd->add_input_section(object, shndx); + switch (entsize) + { + case 1: + posd = new Output_merge_string(addralign); + break; + case 2: + posd = new Output_merge_string(addralign); + break; + case 4: + posd = new Output_merge_string(addralign); + break; + default: + return false; + } } + this->add_output_merge_section(posd, is_string, entsize); + posd->add_input_section(object, shndx); + return true; } @@ -1367,6 +1414,29 @@ Output_section::set_final_data_size() this->set_data_size(off - startoff); } +// Ask each output_section_data member if it wants to change the name +// of the output section. If any of them says yes, use this to set +// the new name. This should be called after all processing of this +// output section is done, but before the name is finally committed to +// the output-section's header. + +bool +Output_section::maybe_modify_output_section_name() +{ + for (Input_section_list::const_iterator it = input_sections_.begin(); + it != input_sections_.end(); + ++it) + { + const char* newname = it->modified_output_section_name(this->name()); + if (newname != NULL) + { + this->set_name(newname); + return true; + } + } + return false; +} + // Write the section header to *OSHDR. template diff --git a/gold/output.h b/gold/output.h index 05ed1f8..95d95f6 100644 --- a/gold/output.h +++ b/gold/output.h @@ -432,6 +432,15 @@ class Output_section_data : public Output_data add_input_section(Relobj* object, unsigned int shndx) { return this->do_add_input_section(object, shndx); } + // This class may change the output section name. This is called + // right before shstrtab is written, so after all input-section + // layout processing is done. The input is the old name, and the + // output should be a new name (which will be copied into permanent + // storage) to change the name, or NULL to keep the name as-is. + virtual const char* + do_modified_output_section_name(const char*) + { return NULL; } + // Given an input OBJECT, an input section index SHNDX within that // object, and an OFFSET relative to the start of that input // section, return whether or not the corresponding offset within @@ -1308,7 +1317,8 @@ 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(const General_options& options, + const char* name, elfcpp::Elf_Word, elfcpp::Elf_Xword); virtual ~Output_section(); // Add a new input section SHNDX, named NAME, with header SHDR, from @@ -1331,6 +1341,13 @@ class Output_section : public Output_data name() const { return this->name_; } + // Modify the section name. This should be called only after this + // section is done being constructed. The input should be a pointer + // into layout's namepool_. + void + set_name(const char* newname) + { this->name_ = newname; } + // Return the section type. elfcpp::Elf_Word type() const @@ -1518,6 +1535,16 @@ class Output_section : public Output_data write_header(const Layout*, const Stringpool*, elfcpp::Shdr_write*) const; + // This class may change the output section name. This is called + // right before shstrtab is written, so after all input-section + // layout processing is done. This calls + // do_modified_output_section_name() on all its output_section_data + // members, and changes the name if any member so suggests. If + // several members would suggest, this takes the first, arbitrarily. + // Return true if the name was modified, false else. + bool + maybe_modify_output_section_name(); + protected: // Return the section index in the output file. unsigned int @@ -1663,6 +1690,15 @@ class Output_section : public Output_data void set_address(uint64_t addr, off_t off, off_t secoff); + // Call modified_output_section_name on the output-section-data object. + const char* + modified_output_section_name(const char* name) const + { + if (this->is_input_section()) + return NULL; + return this->u2_.posd->do_modified_output_section_name(name); + } + // Add an input section, for SHF_MERGE sections. bool add_input_section(Relobj* object, unsigned int shndx) @@ -1777,7 +1813,8 @@ class Output_section : public Output_data // handled. bool add_merge_input_section(Relobj* object, unsigned int shndx, uint64_t flags, - uint64_t entsize, uint64_t addralign); + uint64_t entsize, uint64_t addralign, + bool can_compress_section); // Add an output SHF_MERGE section POSD to this output section. // IS_STRING indicates whether it is a SHF_STRINGS section, and @@ -1789,8 +1826,10 @@ class Output_section : public Output_data // Most of these fields are only valid after layout. + // General options. + const General_options& options_; // The name of the section. This will point into a Stringpool. - const char* const name_; + const char* name_; // The section address is in the parent class. // The section alignment. uint64_t addralign_; diff --git a/gold/po/POTFILES.in b/gold/po/POTFILES.in index 3797b1a..e8a5ba7 100644 --- a/gold/po/POTFILES.in +++ b/gold/po/POTFILES.in @@ -2,6 +2,8 @@ archive.cc archive.h common.cc common.h +compressed_output.cc +compressed_output.h defstd.cc defstd.h dirsearch.cc diff --git a/gold/po/gold.pot b/gold/po/gold.pot index 73f1f01..8d97ea1 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: 2007-11-20 16:37-0800\n" +"POT-Creation-Date: 2007-11-29 16:33-0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -61,6 +61,10 @@ msgstr "" msgid "%s: member at %zu is not an ELF object" msgstr "" +#: compressed_output.cc:140 +msgid "Not compressing section data: zlib error" +msgstr "" + #: dirsearch.cc:68 #, c-format msgid "%s: can not read directory: %s" @@ -179,22 +183,22 @@ msgstr "" msgid "symbol %s has undefined version %s" msgstr "" -#: errors.cc:77 +#: errors.cc:88 #, c-format msgid "%s: warning: " msgstr "" -#: errors.cc:112 +#: errors.cc:127 #, c-format msgid "%s: %s: warning: " msgstr "" -#: errors.cc:136 +#: errors.cc:154 #, c-format msgid "%s: %s: undefined reference to '%s'\n" msgstr "" -#: errors.cc:146 +#: errors.cc:164 #, c-format msgid "%s: " msgstr "" @@ -271,62 +275,62 @@ msgstr "" msgid "cannot mix -static with dynamic object %s" msgstr "" -#: gold-threads.cc:69 +#: gold-threads.cc:102 #, c-format msgid "pthead_mutextattr_init failed: %s" msgstr "" -#: gold-threads.cc:73 +#: gold-threads.cc:106 #, c-format msgid "pthread_mutextattr_settype failed: %s" msgstr "" -#: gold-threads.cc:78 +#: gold-threads.cc:111 #, c-format msgid "pthread_mutex_init failed: %s" msgstr "" -#: gold-threads.cc:82 +#: gold-threads.cc:115 #, c-format msgid "pthread_mutexattr_destroy failed: %s" msgstr "" -#: gold-threads.cc:89 +#: gold-threads.cc:122 #, c-format msgid "pthread_mutex_destroy failed: %s" msgstr "" -#: gold-threads.cc:97 +#: gold-threads.cc:130 #, c-format msgid "pthread_mutex_lock failed: %s" msgstr "" -#: gold-threads.cc:105 +#: gold-threads.cc:138 #, c-format msgid "pthread_mutex_unlock failed: %s" msgstr "" -#: gold-threads.cc:193 +#: gold-threads.cc:219 #, c-format msgid "pthread_cond_init failed: %s" msgstr "" -#: gold-threads.cc:200 +#: gold-threads.cc:226 #, c-format msgid "pthread_cond_destroy failed: %s" msgstr "" -#: gold-threads.cc:208 +#: gold-threads.cc:235 #, c-format msgid "pthread_cond_wait failed: %s" msgstr "" -#: gold-threads.cc:216 +#: gold-threads.cc:243 #, c-format msgid "pthread_cond_signal failed: %s" msgstr "" -#: gold-threads.cc:224 +#: gold-threads.cc:251 #, c-format msgid "pthread_cond_broadcast failed: %s" msgstr "" @@ -371,11 +375,11 @@ msgstr "" msgid "both SUN and GNU model TLS relocations" msgstr "" -#: merge.cc:283 +#: merge.cc:464 msgid "mergeable string section length not multiple of character size" msgstr "" -#: merge.cc:299 +#: merge.cc:480 msgid "entry in mergeable string section not null terminated" msgstr "" @@ -419,7 +423,7 @@ msgstr "" msgid "section %u in section group %u out of range" msgstr "" -#: object.cc:534 reloc.cc:226 reloc.cc:493 +#: object.cc:534 reloc.cc:229 reloc.cc:496 #, c-format msgid "relocation section %u has bad info %u" msgstr "" @@ -549,314 +553,331 @@ msgstr "" msgid "Bind defined symbols locally" msgstr "" -#: options.cc:379 +#: options.cc:385 +msgid "Compress .debug_* sections in the output file (default is none)" +msgstr "" + +#: options.cc:387 +msgid "--compress-debug-sections=[none" +msgstr "" + +#: options.cc:387 +msgid "]" +msgstr "" + +#: options.cc:390 msgid "Demangle C++ symbols in log messages" msgstr "" -#: options.cc:382 +#: options.cc:393 msgid "Do not demangle C++ symbols in log messages" msgstr "" -#: options.cc:385 +#: options.cc:396 msgid "Try to detect violations of the One Definition Rule" msgstr "" -#: options.cc:387 +#: options.cc:398 msgid "Export all dynamic symbols" msgstr "" -#: options.cc:389 +#: options.cc:400 msgid "Create exception frame header" msgstr "" -#: options.cc:391 +#: options.cc:402 msgid "Set dynamic linker path" msgstr "" -#: options.cc:392 +#: options.cc:403 msgid "-I PROGRAM, --dynamic-linker PROGRAM" msgstr "" -#: options.cc:394 +#: options.cc:405 msgid "Search for library LIBNAME" msgstr "" -#: options.cc:395 +#: options.cc:406 msgid "-lLIBNAME, --library LIBNAME" msgstr "" -#: options.cc:397 +#: options.cc:408 msgid "Add directory to search path" msgstr "" -#: options.cc:398 +#: options.cc:409 msgid "-L DIR, --library-path DIR" msgstr "" -#: options.cc:400 +#: options.cc:411 msgid "Ignored for compatibility" msgstr "" -#: options.cc:402 +#: options.cc:413 msgid "Set output file name" msgstr "" -#: options.cc:403 +#: options.cc:414 msgid "-o FILE, --output FILE" msgstr "" -#: options.cc:405 +#: options.cc:416 msgid "Optimize output file size" msgstr "" -#: options.cc:406 +#: options.cc:417 msgid "-O level" msgstr "" -#: options.cc:408 +#: options.cc:419 msgid "Generate relocatable output" msgstr "" -#: options.cc:410 +#: options.cc:421 msgid "Add DIR to runtime search path" msgstr "" -#: options.cc:411 +#: options.cc:422 msgid "-R DIR, -rpath DIR" msgstr "" -#: options.cc:414 +#: options.cc:425 msgid "Add DIR to link time shared library search path" msgstr "" -#: options.cc:415 +#: options.cc:426 msgid "--rpath-link DIR" msgstr "" -#: options.cc:417 +#: options.cc:428 msgid "Strip all symbols" msgstr "" -#: options.cc:420 +#: options.cc:431 msgid "Strip debug symbols that are unused by gdb (at least versions <= 6.7)" msgstr "" #. This must come after -Sdebug since it's a prefix of it. -#: options.cc:424 +#: options.cc:435 msgid "Strip debugging information" msgstr "" -#: options.cc:426 +#: options.cc:437 msgid "Generate shared library" msgstr "" -#: options.cc:428 +#: options.cc:439 msgid "Do not link against shared libraries" msgstr "" -#: options.cc:430 +#: options.cc:441 msgid "Print resource usage statistics" msgstr "" -#: options.cc:432 +#: options.cc:443 msgid "Set target system root directory" msgstr "" -#: options.cc:433 +#: options.cc:444 msgid "--sysroot DIR" msgstr "" -#: options.cc:434 +#: options.cc:445 msgid "Set the address of the .text section" msgstr "" -#: options.cc:435 +#: options.cc:446 msgid "-Ttext ADDRESS" msgstr "" #. This must come after -Ttext since it's a prefix of it. -#: options.cc:438 +#: options.cc:449 msgid "Read linker script" msgstr "" -#: options.cc:439 +#: options.cc:450 msgid "-T FILE, --script FILE" msgstr "" -#: options.cc:441 +#: options.cc:452 msgid "Run the linker multi-threaded" msgstr "" -#: options.cc:443 +#: options.cc:454 msgid "Do not run the linker multi-threaded" msgstr "" -#: options.cc:445 +#: options.cc:456 msgid "Number of threads to use" msgstr "" -#: options.cc:446 +#: options.cc:457 msgid "--thread-count COUNT" msgstr "" -#: options.cc:449 +#: options.cc:460 msgid "Number of threads to use in initial pass" msgstr "" -#: options.cc:450 +#: options.cc:461 msgid "--thread-count-initial COUNT" msgstr "" -#: options.cc:453 +#: options.cc:464 msgid "Number of threads to use in middle pass" msgstr "" -#: options.cc:454 +#: options.cc:465 msgid "--thread-count-middle COUNT" msgstr "" -#: options.cc:457 +#: options.cc:468 msgid "Number of threads to use in final pass" msgstr "" -#: options.cc:458 +#: options.cc:469 msgid "--thread-count-final COUNT" msgstr "" -#: options.cc:461 +#: options.cc:472 msgid "Include all archive contents" msgstr "" -#: options.cc:465 +#: options.cc:476 msgid "Include only needed archive contents" msgstr "" -#: options.cc:470 +#: options.cc:481 msgid "" "Subcommands as follows:\n" " -z execstack Mark output as requiring executable stack\n" " -z noexecstack Mark output as not requiring executable stack" msgstr "" -#: options.cc:473 +#: options.cc:484 msgid "-z SUBCOMMAND" msgstr "" -#: options.cc:476 +#: options.cc:487 msgid "Start a library search group" msgstr "" -#: options.cc:478 +#: options.cc:489 msgid "End a library search group" msgstr "" -#: options.cc:480 +#: options.cc:491 msgid "Report usage information" msgstr "" -#: options.cc:482 +#: options.cc:493 msgid "Report version information" msgstr "" -#: options.cc:484 +#: options.cc:495 msgid "Turn on debugging (all,task)" msgstr "" -#: options.cc:485 +#: options.cc:496 msgid "--debug=TYPE" msgstr "" -#: options.cc:578 +#: options.cc:590 #, c-format msgid "%s: unrecognized -z subcommand: %s\n" msgstr "" -#: options.cc:601 +#: options.cc:613 #, c-format msgid "%s: unrecognized --debug subcommand: %s\n" msgstr "" -#: options.cc:781 +#: options.cc:793 msgid "unexpected argument" msgstr "" -#: options.cc:788 options.cc:840 options.cc:921 +#: options.cc:800 options.cc:852 options.cc:933 msgid "missing argument" msgstr "" -#: options.cc:801 options.cc:849 +#: options.cc:813 options.cc:861 msgid "unknown option" msgstr "" -#: options.cc:867 +#: options.cc:879 #, c-format msgid "%s: missing group end\n" msgstr "" -#: options.cc:995 +#: options.cc:1007 msgid "may not nest groups" msgstr "" -#: options.cc:1005 +#: options.cc:1017 msgid "group end without group start" msgstr "" -#: options.cc:1015 +#: options.cc:1027 #, c-format msgid "%s: use the --help option for usage information\n" msgstr "" -#: options.cc:1024 +#: options.cc:1036 #, c-format msgid "%s: %s: %s\n" msgstr "" -#: options.cc:1033 +#: options.cc:1045 #, c-format msgid "%s: -%c: %s\n" msgstr "" -#: options.h:393 +#: options.h:372 +#, c-format +msgid "Unsupported argument to --compress-debug-symbols: %s" +msgstr "" + +#: options.h:424 #, c-format msgid "%s: invalid argument to -Ttext: %s\n" msgstr "" -#: options.h:406 +#: options.h:437 #, c-format msgid "%s: invalid thread count: %s\n" msgstr "" -#: output.cc:1108 +#: output.cc:1122 #, c-format msgid "invalid alignment %lu for section \"%s\"" msgstr "" -#: output.cc:1870 +#: output.cc:1941 #, c-format msgid "%s: open: %s" msgstr "" -#: output.cc:1875 +#: output.cc:1953 output.cc:1986 #, c-format -msgid "%s: lseek: %s" +msgid "%s: munmap: %s" msgstr "" -#: output.cc:1878 +#: output.cc:1967 #, c-format -msgid "%s: write: %s" +msgid "%s: lseek: %s" msgstr "" -#: output.cc:1884 +#: output.cc:1970 #, c-format -msgid "%s: mmap: %s" +msgid "%s: write: %s" msgstr "" -#: output.cc:1894 +#: output.cc:1976 #, c-format -msgid "%s: munmap: %s" +msgid "%s: mmap: %s" msgstr "" -#: output.cc:1898 +#: output.cc:1990 #, c-format msgid "%s: close: %s" msgstr "" @@ -877,22 +898,22 @@ msgstr "" msgid "%s: not an object or archive" msgstr "" -#: reloc.cc:245 reloc.cc:511 +#: reloc.cc:248 reloc.cc:514 #, c-format msgid "relocation section %u uses unexpected symbol table %u" msgstr "" -#: reloc.cc:260 reloc.cc:529 +#: reloc.cc:263 reloc.cc:532 #, c-format msgid "unexpected entsize for reloc section %u: %lu != %u" msgstr "" -#: reloc.cc:269 reloc.cc:538 +#: reloc.cc:272 reloc.cc:541 #, c-format msgid "reloc section %u size %lu uneven" msgstr "" -#: reloc.cc:729 +#: reloc.cc:732 #, c-format msgid "reloc section size %zu is not a multiple of reloc size %d\n" msgstr "" @@ -934,41 +955,41 @@ msgid "" "T" msgstr "" -#: symtab.cc:576 +#: symtab.cc:597 #, c-format msgid "bad global symbol name offset %u at %zu" msgstr "" -#: symtab.cc:654 +#: symtab.cc:675 msgid "too few symbol versions" msgstr "" -#: symtab.cc:683 +#: symtab.cc:704 #, c-format msgid "bad symbol name offset %u at %zu" msgstr "" -#: symtab.cc:737 +#: symtab.cc:758 #, c-format msgid "versym for symbol %zu out of range: %u" msgstr "" -#: symtab.cc:745 +#: symtab.cc:766 #, c-format msgid "versym for symbol %zu has no name: %u" msgstr "" -#: symtab.cc:1463 symtab.cc:1676 +#: symtab.cc:1484 symtab.cc:1697 #, c-format msgid "%s: unsupported symbol section 0x%x" msgstr "" -#: symtab.cc:1800 +#: symtab.cc:1821 #, c-format msgid "%s: undefined reference to '%s'" msgstr "" -#: symtab.cc:1941 +#: symtab.cc:1962 #, c-format msgid "" "while linking %s: symbol '%s' defined in multiple places (possible ODR " @@ -1003,7 +1024,12 @@ msgid "" "This program has absolutely no warranty.\n" msgstr "" -#: workqueue-threads.cc:106 +#: workqueue.cc:484 +#, c-format +msgid "gold task queue:\n" +msgstr "" + +#: workqueue-threads.cc:107 #, c-format msgid "%s failed: %s" msgstr "" diff --git a/gold/stringpool.cc b/gold/stringpool.cc index db04b0c..42a2fda 100644 --- a/gold/stringpool.cc +++ b/gold/stringpool.cc @@ -41,12 +41,21 @@ Stringpool_template::Stringpool_template() } template -Stringpool_template::~Stringpool_template() +void +Stringpool_template::clear() { for (typename std::list::iterator p = this->strings_.begin(); p != this->strings_.end(); ++p) delete[] reinterpret_cast(*p); + this->strings_.clear(); + this->string_set_.clear(); +} + +template +Stringpool_template::~Stringpool_template() +{ + this->clear(); } // Return the length of a string of arbitrary character type. @@ -413,23 +422,38 @@ Stringpool_template::get_offset(const Stringpool_char* s) gold_unreachable(); } -// Write the ELF strtab into the output file at the specified offset. +// Write the ELF strtab into the buffer. template void -Stringpool_template::write(Output_file* of, off_t offset) +Stringpool_template::write_to_buffer(char* buffer, + size_t bufsize) { gold_assert(this->strtab_size_ != 0); - unsigned char* viewu = of->get_output_view(offset, this->strtab_size_); - char* view = reinterpret_cast(viewu); + if (bufsize < this->strtab_size_) // Quiet the compiler in opt mode. + gold_assert(bufsize >= this->strtab_size_); if (this->zero_null_) - view[0] = '\0'; + buffer[0] = '\0'; for (typename String_set_type::const_iterator p = this->string_set_.begin(); p != this->string_set_.end(); ++p) - memcpy(view + p->second.second, p->first, - (string_length(p->first) + 1) * sizeof(Stringpool_char)); - of->write_output_view(offset, this->strtab_size_, viewu); + { + const int len = (string_length(p->first) + 1) * sizeof(Stringpool_char); + gold_assert(p->second.second + len <= this->strtab_size_); + memcpy(buffer + p->second.second, p->first, len); + } +} + +// Write the ELF strtab into the output file at the specified offset. + +template +void +Stringpool_template::write(Output_file* of, off_t offset) +{ + gold_assert(this->strtab_size_ != 0); + unsigned char* view = of->get_output_view(offset, this->strtab_size_); + this->write_to_buffer(reinterpret_cast(view), this->strtab_size_); + of->write_output_view(offset, this->strtab_size_, view); } // Instantiate the templates we need. diff --git a/gold/stringpool.h b/gold/stringpool.h index 80e53be..57725a5 100644 --- a/gold/stringpool.h +++ b/gold/stringpool.h @@ -84,6 +84,10 @@ class Stringpool_template ~Stringpool_template(); + // Clear all the data from the stringpool. + void + clear(); + // Indicate that we should not reserve offset 0 to hold the empty // string when converting the stringpool to a string table. This // should not be called for a proper ELF SHT_STRTAB section. @@ -139,6 +143,12 @@ class Stringpool_template void write(Output_file*, off_t offset); + // Write the string table into the specified buffer, of the + // specified size. buffer_size should be at least + // get_strtab_size(). + void + write_to_buffer(char* buffer, size_t buffer_size); + private: Stringpool_template(const Stringpool_template&); Stringpool_template& operator=(const Stringpool_template&); diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index f908dc3..a3d6aa5 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -445,6 +445,7 @@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ +CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ -- cgit v1.1