OSDN Git Service

From Craig Silverstein: Add support for compressing .debug_str section.
authorIan Lance Taylor <iant@google.com>
Fri, 30 Nov 2007 00:35:27 +0000 (00:35 +0000)
committerIan Lance Taylor <iant@google.com>
Fri, 30 Nov 2007 00:35:27 +0000 (00:35 +0000)
20 files changed:
gold/Makefile.am
gold/Makefile.in
gold/compressed_output.cc [new file with mode: 0644]
gold/compressed_output.h [new file with mode: 0644]
gold/config.in
gold/configure
gold/configure.ac
gold/layout.cc
gold/layout.h
gold/merge.cc
gold/merge.h
gold/options.cc
gold/options.h
gold/output.cc
gold/output.h
gold/po/POTFILES.in
gold/po/gold.pot
gold/stringpool.cc
gold/stringpool.h
gold/testsuite/Makefile.in

index de9be20..84c39b9 100644 (file)
@@ -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 \
index fd981d6..cae5524 100644 (file)
@@ -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 (file)
index 0000000..1006ac8
--- /dev/null
@@ -0,0 +1,267 @@
+// compressed_output.cc -- manage compressed output sections for gold
+
+// Copyright 2007 Free Software Foundation, Inc.
+// Written by Ian Lance Taylor <iant@google.com>.
+
+// 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 <zlib.h>
+#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<Bytef*>(*compressed_data),
+                     compressed_size,
+                     reinterpret_cast<const Bytef*>(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<Object_entry>::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<Object_entry>::const_iterator it = this->objects_.begin();
+       it != this->objects_.end();
+       ++it)
+    {
+      memcpy(uncompressed_data + pos,
+             reinterpret_cast<const char*>(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<char*>(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<typename Char_type>
+bool
+Output_compressed_string<Char_type>::do_add_input_section(Relobj* object,
+                                                          unsigned int shndx)
+{
+  return Output_merge_string<Char_type>::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<typename Char_type>
+void
+Output_compressed_string<Char_type>::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<typename Char_type>
+const char*
+Output_compressed_string<Char_type>::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<typename Char_type>
+void
+Output_compressed_string<Char_type>::do_write(Output_file* of)
+{
+  if (this->compressed_data_ == NULL)
+    Output_merge_string<Char_type>::do_write(of);
+  else
+    {
+      unsigned char* uview = of->get_output_view(this->offset(),
+                                                 this->data_size());
+      char* view = reinterpret_cast<char*>(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<char>;
+
+template
+class Output_compressed_string<uint16_t>;
+
+template
+class Output_compressed_string<uint32_t>;
+
+} // End namespace gold.
diff --git a/gold/compressed_output.h b/gold/compressed_output.h
new file mode 100644 (file)
index 0000000..589dacc
--- /dev/null
@@ -0,0 +1,137 @@
+// compressed_output.h -- compressed output sections for gold  -*- C++ -*-
+
+// Copyright 2007 Free Software Foundation, Inc.
+// Written by Ian Lance Taylor <iant@google.com>.
+
+// 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 <string>
+#include <vector>
+
+#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<Object_entry> 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<typename Char_type>
+class Output_compressed_string : public Output_merge_string<Char_type>
+{
+ public:
+  Output_compressed_string(uint64_t addralign,
+                           const General_options& options)
+    : Output_merge_string<Char_type>(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)
index 7550224..9c0db95 100644 (file)
@@ -67,6 +67,9 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define to 1 if you have the <zlib.h> header file. */
+#undef HAVE_ZLIB_H
+
 /* Name of package */
 #undef PACKAGE
 
index 7648c2c..66e6167 100755 (executable)
@@ -309,7 +309,7 @@ ac_includes_default="\
 # 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 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 <include dir>
   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 <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_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 <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_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 <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_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 <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_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 <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_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 <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_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 <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
@@ -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
index e230b5f..ea4fd67 100644 (file)
@@ -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)
index d95aea4..f7c1e40 100644 (file)
@@ -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);
index 0659d1b..cff29ed 100644 (file)
@@ -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.
index 726a972..215bc34 100644 (file)
@@ -496,13 +496,12 @@ Output_merge_string<Char_type>::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<typename Char_type>
-void
-Output_merge_string<Char_type>::set_final_data_size()
+off_t
+Output_merge_string<Char_type>::finalize_merged_data()
 {
   this->stringpool_.set_string_offsets();
 
@@ -513,10 +512,18 @@ Output_merge_string<Char_type>::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<typename Char_type>
+void
+Output_merge_string<Char_type>::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.
index 70fe6b7..a28ff42 100644 (file)
@@ -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.
index fb79901..f5fc8da 100644 (file)
@@ -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_(),
index c7b08e8..b327aa9 100644 (file)
@@ -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_;
index d89c72a..351c21d 100644 (file)
@@ -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<size, big_endian>* 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<char>(addralign, this->options_);
+         break;
+        case 2:
+         posd = new Output_compressed_string<uint16_t>(addralign,
+                                                       this->options_);
+         break;
+        case 4:
+         posd = new Output_compressed_string<uint32_t>(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<char>(addralign);
-      else if (entsize == 2)
-       posd = new Output_merge_string<uint16_t>(addralign);
-      else if (entsize == 4)
-       posd = new Output_merge_string<uint32_t>(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<char>(addralign);
+         break;
+        case 2:
+         posd = new Output_merge_string<uint16_t>(addralign);
+         break;
+        case 4:
+         posd = new Output_merge_string<uint32_t>(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<int size, bool big_endian>
index 05ed1f8..95d95f6 100644 (file)
@@ -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<size, big_endian>*) 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_;
index 3797b1a..e8a5ba7 100644 (file)
@@ -2,6 +2,8 @@ archive.cc
 archive.h
 common.cc
 common.h
+compressed_output.cc
+compressed_output.h
 defstd.cc
 defstd.h
 dirsearch.cc
index 73f1f01..8d97ea1 100644 (file)
@@ -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 <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\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 ""
index db04b0c..42a2fda 100644 (file)
@@ -41,12 +41,21 @@ Stringpool_template<Stringpool_char>::Stringpool_template()
 }
 
 template<typename Stringpool_char>
-Stringpool_template<Stringpool_char>::~Stringpool_template()
+void
+Stringpool_template<Stringpool_char>::clear()
 {
   for (typename std::list<Stringdata*>::iterator p = this->strings_.begin();
        p != this->strings_.end();
        ++p)
     delete[] reinterpret_cast<char*>(*p);
+  this->strings_.clear();
+  this->string_set_.clear();
+}
+
+template<typename Stringpool_char>
+Stringpool_template<Stringpool_char>::~Stringpool_template()
+{
+  this->clear();
 }
 
 // Return the length of a string of arbitrary character type.
@@ -413,23 +422,38 @@ Stringpool_template<Stringpool_char>::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<typename Stringpool_char>
 void
-Stringpool_template<Stringpool_char>::write(Output_file* of, off_t offset)
+Stringpool_template<Stringpool_char>::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<char*>(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<typename Stringpool_char>
+void
+Stringpool_template<Stringpool_char>::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<char*>(view), this->strtab_size_);
+  of->write_output_view(offset, this->strtab_size_, view);
 }
 
 // Instantiate the templates we need.
index 80e53be..57725a5 100644 (file)
@@ -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&);
index f908dc3..a3d6aa5 100644 (file)
@@ -445,6 +445,7 @@ CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
+CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CXX = @CXX@
 CXXCPP = @CXXCPP@