mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-23 20:19:49 +00:00
Rework File_read interface. Get file size. Use pread when
available.
This commit is contained in:
parent
bae3688d8f
commit
82dcae9de0
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
117
gold/configure
vendored
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
125
gold/fileread.cc
125
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;
|
||||
}
|
||||
|
||||
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);
|
||||
return v;
|
||||
}
|
||||
|
||||
// This implementation of get_view just reads into a memory buffer,
|
||||
|
@ -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.
|
||||
|
@ -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
39
gold/pread.c
Normal 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);
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
Loading…
Reference in New Issue
Block a user