Rework File_read interface. Get file size. Use pread when

available.
This commit is contained in:
Ian Lance Taylor 2007-09-25 06:43:17 +00:00
parent bae3688d8f
commit 82dcae9de0
13 changed files with 293 additions and 125 deletions

View 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

View 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

View 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);

View 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

117
gold/configure vendored
View File

@ -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

View 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)

View 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;
}
if (pbytes != NULL)
*pbytes = bytes;
else if (bytes != size)
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);
}
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));
if (poff + psize >= this->size_)
{
psize = this->size_ - poff;
gold_assert(psize >= size);
}
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);
this->do_read_exact(poff, psize, p);
File_read::View* v = new File_read::View(poff, psize, p);
ins.first->second = v;
if (bytes - (start - poff) >= size)
return v;
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);
}
// This implementation of get_view just reads into a memory buffer,

View 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.

View 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++.

39
gold/pread.c Normal file
View File

@ -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);
}

View 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;

View 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

View 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 \