Rework File_read interface. Get file size. Use pread when
authorIan Lance Taylor <iant@google.com>
Tue, 25 Sep 2007 06:43:17 +0000 (06:43 +0000)
committerIan Lance Taylor <iant@google.com>
Tue, 25 Sep 2007 06:43:17 +0000 (06:43 +0000)
available.

13 files changed:
gold/Makefile.am
gold/Makefile.in
gold/archive.cc
gold/config.in
gold/configure
gold/configure.ac
gold/fileread.cc
gold/fileread.h
gold/gold.h
gold/pread.c [new file with mode: 0644]
gold/readsyms.cc
gold/script.cc
gold/testsuite/Makefile.in

index 11476f8..1710aa6 100644 (file)
@@ -86,8 +86,8 @@ deps_var = libgold.a $(LIBINTL_DEP)
 ldadd_var = libgold.a $(LIBINTL)
 
 ld_new_SOURCES = $(sources_var)
-ld_new_DEPENDENCIES = $(deps_var)
-ld_new_LDADD = $(ldadd_var)
+ld_new_DEPENDENCIES = $(deps_var) $(LIBOBJS)
+ld_new_LDADD = $(ldadd_var) $(LIBOBJS)
 
 # Use an explicit dependency for the bison generated header file.
 script.$(OBJEXT): yyscript.h
index f2ef3a8..2780238 100644 (file)
@@ -48,8 +48,8 @@ DIST_COMMON = README $(am__configure_deps) $(srcdir)/../config.guess \
        $(srcdir)/../install-sh $(srcdir)/../missing \
        $(srcdir)/../mkinstalldirs $(srcdir)/Makefile.am \
        $(srcdir)/Makefile.in $(srcdir)/config.in \
-       $(top_srcdir)/configure $(top_srcdir)/po/Make-in yyscript.c \
-       yyscript.h
+       $(top_srcdir)/configure $(top_srcdir)/po/Make-in pread.c \
+       yyscript.c yyscript.h
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
@@ -90,6 +90,7 @@ am_ld_new_OBJECTS = $(am__objects_5)
 ld_new_OBJECTS = $(am_ld_new_OBJECTS)
 am__DEPENDENCIES_1 =
 am__DEPENDENCIES_2 = libgold.a $(am__DEPENDENCIES_1)
+am__DEPENDENCIES_3 = @LIBOBJS@
 am__ld1_SOURCES_DIST = main.cc i386.cc
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am_ld1_OBJECTS = $(am__objects_5)
 ld1_OBJECTS = $(am_ld1_OBJECTS)
@@ -327,8 +328,8 @@ sources_var = main.cc $(TARGETFILES)
 deps_var = libgold.a $(LIBINTL_DEP)
 ldadd_var = libgold.a $(LIBINTL)
 ld_new_SOURCES = $(sources_var)
-ld_new_DEPENDENCIES = $(deps_var)
-ld_new_LDADD = $(ldadd_var)
+ld_new_DEPENDENCIES = $(deps_var) $(LIBOBJS)
+ld_new_LDADD = $(ldadd_var) $(LIBOBJS)
 POTFILES = $(CCFILES) $(HFILES) $(TARGETFILES)
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ld1_SOURCES = $(sources_var)
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ld1_DEPENDENCIES = $(deps_var) gcctestdir1/ld
@@ -430,6 +431,7 @@ mostlyclean-compile:
 distclean-compile:
        -rm -f *.tab.c
 
+@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)/defstd.Po@am__quote@
@@ -893,7 +895,7 @@ clean-am: clean-checkPROGRAMS clean-generic clean-noinstLIBRARIES \
 
 distclean: distclean-recursive
        -rm -f $(am__CONFIG_DISTCLEAN_FILES)
-       -rm -rf ./$(DEPDIR)
+       -rm -rf $(DEPDIR) ./$(DEPDIR)
        -rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
        distclean-hdr distclean-tags
@@ -921,7 +923,7 @@ installcheck-am:
 maintainer-clean: maintainer-clean-recursive
        -rm -f $(am__CONFIG_DISTCLEAN_FILES)
        -rm -rf $(top_srcdir)/autom4te.cache
-       -rm -rf ./$(DEPDIR)
+       -rm -rf $(DEPDIR) ./$(DEPDIR)
        -rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
index 5ab3696..7398076 100644 (file)
@@ -326,16 +326,12 @@ Archive::include_all_members(Symbol_table* symtab, Layout* layout,
                              Input_objects* input_objects)
 {
   off_t off = sarmag;
+  off_t filesize = this->input_file_->file().filesize();
   while (true)
     {
-      unsigned char hdr_buf[sizeof(Archive_header)];
-      off_t bytes;
-      this->input_file_->file().read_up_to(off, sizeof(Archive_header),
-                                          hdr_buf, &bytes);
-
-      if (bytes < sizeof(Archive_header))
+      if (filesize - off < sizeof(Archive_header))
         {
-          if (bytes != 0)
+          if (filesize != off)
             {
               fprintf(stderr, _("%s: %s: short archive header at %ld\n"),
                       program_name, this->name().c_str(),
@@ -346,6 +342,9 @@ Archive::include_all_members(Symbol_table* symtab, Layout* layout,
           break;
         }
 
+      unsigned char hdr_buf[sizeof(Archive_header)];
+      this->input_file_->file().read(off, sizeof(Archive_header), hdr_buf);
+
       const Archive_header* hdr =
        reinterpret_cast<const Archive_header*>(hdr_buf);
       std::string name;
@@ -380,11 +379,14 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
   size_t memoff = off + sizeof(Archive_header);
 
   // Read enough of the file to pick up the entire ELF header.
-  int ehdr_size = elfcpp::Elf_sizes<64>::ehdr_size;
-  unsigned char ehdr_buf[ehdr_size];
-  off_t bytes;
-  this->input_file_->file().read_up_to(memoff, ehdr_size, ehdr_buf, &bytes);
-  if (bytes < 4)
+  unsigned char ehdr_buf[elfcpp::Elf_sizes<64>::ehdr_size];
+
+  off_t filesize = this->input_file_->file().filesize();
+  int read_size = elfcpp::Elf_sizes<64>::ehdr_size;
+  if (filesize - memoff < read_size)
+    read_size = filesize - memoff;
+
+  if (read_size < 4)
     {
       fprintf(stderr, _("%s: %s: member at %ld is not an ELF object"),
              program_name, this->name().c_str(),
@@ -392,6 +394,8 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
       gold_exit(false);
     }
 
+  this->input_file_->file().read(memoff, read_size, ehdr_buf);
+
   static unsigned char elfmagic[4] =
     {
       elfcpp::ELFMAG0, elfcpp::ELFMAG1,
@@ -407,7 +411,8 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
 
   Object* obj = make_elf_object((std::string(this->input_file_->filename())
                                 + "(" + n + ")"),
-                               this->input_file_, memoff, ehdr_buf, bytes);
+                               this->input_file_, memoff, ehdr_buf,
+                               read_size);
 
   input_objects->add_object(obj);
 
index ba337b8..bbdf051 100644 (file)
@@ -19,6 +19,9 @@
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
+/* Define to 1 if you have the `pread' function. */
+#undef HAVE_PREAD
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
index 98c06bc..e9c942a 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 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 WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CXXFLAGS CXXCPP EGREP MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LIBOBJS 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 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 WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CXXFLAGS LIBOBJS CXXCPP EGREP MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -4404,6 +4404,119 @@ WARN_CXXFLAGS=`echo ${WARN_CFLAGS} | sed -e 's/-Wstrict-prototypes//' -e 's/-Wmi
 LFS_CXXFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
 
 
+
+for ac_func in pread
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+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.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* 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 $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  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
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  case $LIBOBJS in
+    "$ac_func.$ac_objext"   | \
+  *" $ac_func.$ac_objext"   | \
+    "$ac_func.$ac_objext "* | \
+  *" $ac_func.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" ;;
+esac
+
+fi
+done
+
+
+
 ac_ext=cc
 ac_cpp='$CXXCPP $CPPFLAGS'
 ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -6030,12 +6143,12 @@ s,@WARN_CFLAGS@,$WARN_CFLAGS,;t t
 s,@NO_WERROR@,$NO_WERROR,;t t
 s,@WARN_CXXFLAGS@,$WARN_CXXFLAGS,;t t
 s,@LFS_CXXFLAGS@,$LFS_CXXFLAGS,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
 s,@CXXCPP@,$CXXCPP,;t t
 s,@EGREP@,$EGREP,;t t
 s,@MAINTAINER_MODE_TRUE@,$MAINTAINER_MODE_TRUE,;t t
 s,@MAINTAINER_MODE_FALSE@,$MAINTAINER_MODE_FALSE,;t t
 s,@MAINT@,$MAINT,;t t
-s,@LIBOBJS@,$LIBOBJS,;t t
 s,@LTLIBOBJS@,$LTLIBOBJS,;t t
 CEOF
 
index 1294fa6..fcb176f 100644 (file)
@@ -106,6 +106,8 @@ dnl host dependent.  If build == host, we can check getconf LFS_CFLAGS.
 LFS_CXXFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
 AC_SUBST(LFS_CXXFLAGS)
 
+AC_REPLACE_FUNCS(pread)
+
 AC_LANG_PUSH(C++)
 
 AC_CHECK_HEADERS(tr1/unordered_set tr1/unordered_map)
index ee2ae73..9b800e8 100644 (file)
@@ -89,8 +89,23 @@ File_read::open(const std::string& name)
              && this->descriptor_ < 0
              && this->name_.empty());
   this->name_ = name;
+
   this->descriptor_ = ::open(this->name_.c_str(), O_RDONLY);
+
+  if (this->descriptor_ >= 0)
+    {
+      struct stat s;
+      if (::fstat(this->descriptor_, &s) < 0)
+       {
+         fprintf(stderr, _("%s: %s: fstat failed: %s"), program_name,
+                 this->name_.c_str(), strerror(errno));
+         gold_exit(false);
+       }
+      this->size_ = s.st_size;
+    }
+
   ++this->lock_count_;
+
   return this->descriptor_ >= 0;
 }
 
@@ -98,14 +113,14 @@ File_read::open(const std::string& name)
 
 bool
 File_read::open(const std::string& name, const unsigned char* contents,
-               off_t contents_size)
+               off_t size)
 {
   gold_assert(this->lock_count_ == 0
              && this->descriptor_ < 0
              && this->name_.empty());
   this->name_ = name;
   this->contents_ = contents;
-  this->contents_size_ = contents_size;
+  this->size_ = size;
   ++this->lock_count_;
   return true;
 }
@@ -144,50 +159,45 @@ File_read::find_view(off_t start, off_t size)
   return p->second;
 }
 
-// Read data from the file.  Return the number of bytes read.  If
-// PBYTES is not NULL, store the number of bytes in *PBYTES, otherwise
-// require that we read exactly the number of bytes requested.
+// Read SIZE bytes from the file starting at offset START.  Read into
+// the buffer at P.  Return the number of bytes read, which should
+// always be at least SIZE except at the end of the file.
 
 off_t
-File_read::do_read(off_t start, off_t size, void* p, off_t* pbytes)
+File_read::do_read(off_t start, off_t size, void* p)
 {
   gold_assert(this->lock_count_ > 0);
 
-  off_t bytes;
-  if (this->contents_ == NULL)
+  if (this->contents_ != NULL)
     {
-      int o = this->descriptor_;
-
-      if (lseek(o, start, SEEK_SET) < 0)
-       {
-         fprintf(stderr, _("%s: %s: lseek to %lld failed: %s"),
-                 program_name, this->filename().c_str(),
-                 static_cast<long long>(start),
-                 strerror(errno));
-         gold_exit(false);
-       }
-
-      bytes = ::read(o, p, size);
-      if (bytes < 0)
-       {
-         fprintf(stderr, _("%s: %s: read failed: %s\n"),
-                 program_name, this->filename().c_str(), strerror(errno));
-         gold_exit(false);
-       }
-    }
-  else
-    {
-      bytes = this->contents_size_ - start;
+      off_t bytes = this->size_ - start;
       if (bytes < 0)
        bytes = 0;
       else if (bytes > size)
        bytes = size;
       memcpy(p, this->contents_ + start, bytes);
+      return bytes;
+    }
+
+  off_t bytes = ::pread(this->descriptor_, p, size, start);
+  if (bytes < 0)
+    {
+      fprintf(stderr, _("%s: %s: pread failed: %s\n"),
+             program_name, this->filename().c_str(), strerror(errno));
+      gold_exit(false);
     }
 
-  if (pbytes != NULL)
-    *pbytes = bytes;
-  else if (bytes != size)
+  return bytes;
+}
+
+// Read exactly SIZE bytes from the file starting at offset START.
+// Read into the buffer at P.
+
+void
+File_read::do_read_exact(off_t start, off_t size, void* p)
+{
+  off_t bytes = this->do_read(start, size, p);
+  if (bytes != size)
     {
       fprintf(stderr,
              _("%s: %s: file too short: read only %lld of %lld "
@@ -198,8 +208,6 @@ File_read::do_read(off_t start, off_t size, void* p, off_t* pbytes)
              static_cast<long long>(start));
       gold_exit(false);
     }
-
-  return bytes;
 }
 
 // Read data from the file.
@@ -216,24 +224,7 @@ File_read::read(off_t start, off_t size, void* p)
       return;
     }
 
-  this->do_read(start, size, p, NULL);
-}
-
-void
-File_read::read_up_to(off_t start, off_t size, void* p, off_t* pbytes)
-{
-  gold_assert(this->lock_count_ > 0);
-
-  File_read::View* pv = this->find_view(start, size);
-  if (pv != NULL)
-    {
-      memcpy(p, pv->data() + (start - pv->start()), size);
-      if (pbytes != NULL)
-       *pbytes = size;
-      return;
-    }
-
-  this->do_read(start, size, p, pbytes);
+  this->do_read_exact(start, size, p);
 }
 
 // Find an existing view or make a new one.
@@ -260,28 +251,24 @@ File_read::find_or_make_view(off_t start, off_t size)
       this->saved_views_.push_back(v);
     }
 
-  // We need to read data from the file.
+  // We need to read data from the file.  We read full pages for
+  // greater efficiency on small files.
 
   off_t psize = File_read::pages(size + (start - poff));
-  unsigned char* p = new unsigned char[psize];
 
-  off_t got_bytes;
-  off_t bytes = this->do_read(poff, psize, p, &got_bytes);
-
-  File_read::View* v = new File_read::View(poff, bytes, p);
+  if (poff + psize >= this->size_)
+    {
+      psize = this->size_ - poff;
+      gold_assert(psize >= size);
+    }
 
-  ins.first->second = v;
+  unsigned char* p = new unsigned char[psize];
 
-  if (bytes - (start - poff) >= size)
-    return v;
+  this->do_read_exact(poff, psize, p);
 
-  fprintf(stderr,
-         _("%s: %s: file too short: read only %lld of %lld bytes at %lld\n"),
-         program_name, this->filename().c_str(),
-         static_cast<long long>(bytes - (start - poff)),
-         static_cast<long long>(size),
-         static_cast<long long>(start));
-  gold_exit(false);
+  File_read::View* v = new File_read::View(poff, psize, p);
+  ins.first->second = v;
+  return v;
 }
 
 // This implementation of get_view just reads into a memory buffer,
index 781031a..ef5efc0 100644 (file)
@@ -45,8 +45,8 @@ class File_read
 {
  public:
   File_read()
-    : name_(), descriptor_(-1), lock_count_(0), views_(),
-      saved_views_(), contents_(NULL), contents_size_(0)
+    : name_(), descriptor_(-1), size_(0), lock_count_(0), views_(),
+      saved_views_(), contents_(NULL)
   { }
 
   ~File_read();
@@ -80,6 +80,11 @@ class File_read
   bool
   is_locked();
 
+  // Return the size of the file.
+  off_t
+  filesize() const
+  { return this->size_; }
+
   // Return a view into the file starting at file offset START for
   // SIZE bytes.  The pointer will remain valid until the File_read is
   // unlocked.  It is an error if we can not read enough data from the
@@ -92,11 +97,6 @@ class File_read
   void
   read(off_t start, off_t size, void* p);
 
-  // Read up to SIZE bytes from the file into the buffer P starting at
-  // file offset START.  Set *PBYTES to the number of bytes read.
-  void
-  read_up_to(off_t start, off_t size, void* p, off_t* pbytes);
-
   // Return a lasting view into the file starting at file offset START
   // for SIZE bytes.  This is allocated with new, and the caller is
   // responsible for deleting it when done.  The data associated with
@@ -159,7 +159,11 @@ class File_read
 
   // Read data from the file into a buffer.
   off_t
-  do_read(off_t start, off_t size, void* p, off_t* pbytes);
+  do_read(off_t start, off_t size, void* p);
+
+  // Read an exact number of bytes into a buffer.
+  void
+  do_read_exact(off_t start, off_t size, void* p);
 
   // Find or make a view into the file.
   View*
@@ -192,6 +196,8 @@ class File_read
   std::string name_;
   // File descriptor.
   int descriptor_;
+  // File size.
+  off_t size_;
   // Number of locks on the file.
   int lock_count_;
   // Buffered views into the file.
@@ -201,8 +207,6 @@ class File_read
   Saved_views saved_views_;
   // Specified file contents.  Used only for testing purposes.
   const unsigned char* contents_;
-  // Specified file size.  Used only for testing purposes.
-  off_t contents_size_;
 };
 
 // A view of file data that persists even when the file is unlocked.
index 3752846..14d4aee 100644 (file)
@@ -98,6 +98,10 @@ struct hash<T*>
 
 #endif
 
+#ifndef HAVE_PREAD
+extern "C" ssize_t pread(int, void*, size_t, off_t);
+#endif
+
 namespace gold
 {
 // This is a hack to work around a problem with older versions of g++.
diff --git a/gold/pread.c b/gold/pread.c
new file mode 100644 (file)
index 0000000..1b0cf40
--- /dev/null
@@ -0,0 +1,39 @@
+/* pread.c -- version of pread for gold.  */
+
+/* Copyright 2006, 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.  */
+
+/* This file implements pread for systems which don't have it.  This
+   file is only compiled if pread is not present on the system.  This
+   is not an exact version of pread, as it does not preserve the
+   current file offset.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+
+ssize_t
+pread(int fd, void* buf, size_t count, off_t offset)
+{
+  if (lseek(fd, offset, SEEK_SET) != offset)
+    return -1;
+  return read(fd, buf, count);
+}
index 5c5594d..bbeb425 100644 (file)
@@ -86,12 +86,24 @@ Read_symbols::run(Workqueue* workqueue)
 
   // Read enough of the file to pick up the entire ELF header.
 
-  const int ehdr_size = elfcpp::Elf_sizes<64>::ehdr_size;
-  unsigned char ehdr_buf[ehdr_size];
-  off_t bytes;
-  input_file->file().read_up_to(0, ehdr_size, ehdr_buf, &bytes);
+  off_t filesize = input_file->file().filesize();
 
-  if (bytes >= 4)
+  if (filesize == 0)
+    {
+      fprintf(stderr, _("%s: %s: file is empty\n"),
+             program_name, input_file->file().filename().c_str());
+      gold_exit(false);
+    }
+
+  unsigned char ehdr_buf[elfcpp::Elf_sizes<64>::ehdr_size];
+
+  int read_size = elfcpp::Elf_sizes<64>::ehdr_size;
+  if (filesize < read_size)
+    read_size = filesize;
+
+  input_file->file().read(0, read_size, ehdr_buf);
+
+  if (read_size >= 4)
     {
       static unsigned char elfmagic[4] =
        {
@@ -103,7 +115,7 @@ Read_symbols::run(Workqueue* workqueue)
          // This is an ELF object.
 
          Object* obj = make_elf_object(input_file->filename(),
-                                       input_file, 0, ehdr_buf, bytes);
+                                       input_file, 0, ehdr_buf, read_size);
 
          // We don't have a way to record a non-archive in an input
          // group.  If this is an ordinary object file, we can't
@@ -132,7 +144,7 @@ Read_symbols::run(Workqueue* workqueue)
        }
     }
 
-  if (bytes >= Archive::sarmag)
+  if (read_size >= Archive::sarmag)
     {
       if (memcmp(ehdr_buf, Archive::armag, Archive::sarmag) == 0)
        {
@@ -151,18 +163,11 @@ Read_symbols::run(Workqueue* workqueue)
        }
     }
 
-  if (bytes == 0)
-    {
-      fprintf(stderr, _("%s: %s: file is empty\n"),
-             program_name, input_file->file().filename().c_str());
-      gold_exit(false);
-    }
-
   // Try to parse this file as a script.
   if (read_input_script(workqueue, this->options_, this->symtab_,
                        this->layout_, this->dirpath_, this->input_objects_,
                        this->input_group_, this->input_argument_, input_file,
-                       ehdr_buf, bytes, this->this_blocker_,
+                       ehdr_buf, read_size, this->this_blocker_,
                        this->next_blocker_))
     return;
 
index 53cd493..950fa15 100644 (file)
@@ -299,17 +299,21 @@ class Lex
 void
 Lex::read_file(std::string* contents)
 {
+  off_t filesize = this->input_file_->file().filesize();
   contents->clear();
+  contents->reserve(filesize);
+
   off_t off = 0;
-  off_t got;
   unsigned char buf[BUFSIZ];
-  do
+  while (off < filesize)
     {
-      this->input_file_->file().read_up_to(off, sizeof buf, buf, &got);
-      contents->append(reinterpret_cast<char*>(&buf[0]), got);
-      off += got;
+      off_t get = BUFSIZ;
+      if (get > filesize - off)
+       get = filesize - off;
+      this->input_file_->file().read(off, get, buf);
+      contents->append(reinterpret_cast<char*>(&buf[0]), get);
+      off += get;
     }
-  while (got == sizeof buf);
 }
 
 // Return whether C can be the start of a name, if the next character
index 24eda43..edf32e8 100644 (file)
@@ -464,9 +464,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__confi
              exit 1;; \
          esac; \
        done; \
-       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  testsuite/Makefile'; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  testsuite/Makefile'; \
        cd $(top_srcdir) && \
-         $(AUTOMAKE) --gnu  testsuite/Makefile
+         $(AUTOMAKE) --foreign  testsuite/Makefile
 .PRECIOUS: Makefile
 Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
        @case '$?' in \