summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/Makefile.am4
-rw-r--r--gold/Makefile.in14
-rw-r--r--gold/archive.cc31
-rw-r--r--gold/config.in3
-rwxr-xr-xgold/configure117
-rw-r--r--gold/configure.ac2
-rw-r--r--gold/fileread.cc125
-rw-r--r--gold/fileread.h24
-rw-r--r--gold/gold.h4
-rw-r--r--gold/pread.c39
-rw-r--r--gold/readsyms.cc35
-rw-r--r--gold/script.cc16
-rw-r--r--gold/testsuite/Makefile.in4
13 files changed, 293 insertions, 125 deletions
diff --git a/gold/Makefile.am b/gold/Makefile.am
index 11476f80b9..1710aa6068 100644
--- a/gold/Makefile.am
+++ b/gold/Makefile.am
@@ -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
diff --git a/gold/Makefile.in b/gold/Makefile.in
index f2ef3a8b25..2780238186 100644
--- a/gold/Makefile.in
+++ b/gold/Makefile.in
@@ -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
diff --git a/gold/archive.cc b/gold/archive.cc
index 5ab3696c7c..7398076bfb 100644
--- a/gold/archive.cc
+++ b/gold/archive.cc
@@ -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);
diff --git a/gold/config.in b/gold/config.in
index ba337b88aa..bbdf05130d 100644
--- a/gold/config.in
+++ b/gold/config.in
@@ -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
diff --git a/gold/configure b/gold/configure
index 98c06bc5ed..e9c942a802 100755
--- a/gold/configure
+++ b/gold/configure
@@ -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
diff --git a/gold/configure.ac b/gold/configure.ac
index 1294fa64d4..fcb176f7f1 100644
--- a/gold/configure.ac
+++ b/gold/configure.ac
@@ -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)
diff --git a/gold/fileread.cc b/gold/fileread.cc
index ee2ae73f61..9b800e81fc 100644
--- a/gold/fileread.cc
+++ b/gold/fileread.cc
@@ -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,
diff --git a/gold/fileread.h b/gold/fileread.h
index 781031aef5..ef5efc0b9b 100644
--- a/gold/fileread.h
+++ b/gold/fileread.h
@@ -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.
diff --git a/gold/gold.h b/gold/gold.h
index 3752846436..14d4aeec98 100644
--- a/gold/gold.h
+++ b/gold/gold.h
@@ -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
index 0000000000..1b0cf40e74
--- /dev/null
+++ b/gold/pread.c
@@ -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);
+}
diff --git a/gold/readsyms.cc b/gold/readsyms.cc
index 5c5594daab..bbeb425f98 100644
--- a/gold/readsyms.cc
+++ b/gold/readsyms.cc
@@ -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;
diff --git a/gold/script.cc b/gold/script.cc
index 53cd4931c5..950fa15810 100644
--- a/gold/script.cc
+++ b/gold/script.cc
@@ -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
diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in
index 24eda432fa..edf32e8ada 100644
--- a/gold/testsuite/Makefile.in
+++ b/gold/testsuite/Makefile.in
@@ -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 \