readelf: use fseeko64 or fseeko if possible

Changes readelf to make use first of fseeko64 and then fseeko,
depending on which of those is available. If neither is available,
reverts to the previous behavior of using fseek.

This is necessary when building readelf for LLP64 systems, where a
long will only be 32 bits wide. If the elf file in question is >= 2 GiB,
that is greater than the max long value and therefore fseek will fail
indicating that the offset is negative. On such systems, making use of
fseeko64 or fseeko will result in the ability so seek past the 2 GiB
max long boundary.

Note that large archive handling in readelf remains to be fixed.
This commit is contained in:
Brett Werling 2022-11-17 08:34:19 -06:00 committed by Alan Modra
parent 38c917d808
commit d82e33decc
3 changed files with 26 additions and 12 deletions

View File

@ -67,6 +67,12 @@
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the `fseeko' function. */
#undef HAVE_FSEEKO
/* Define to 1 if you have the `fseeko64' function. */
#undef HAVE_FSEEKO64
/* Define to 1 if you have the `getc_unlocked' function. */
#undef HAVE_GETC_UNLOCKED

2
binutils/configure vendored
View File

@ -13155,7 +13155,7 @@ $as_echo "#define HAVE_MMAP 1" >>confdefs.h
fi
rm -f conftest.mmap conftest.txt
for ac_func in getc_unlocked mkdtemp mkstemp utimensat utimes
for ac_func in getc_unlocked mkdtemp mkstemp utimensat utimes fseeko fseeko64
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"

View File

@ -178,6 +178,14 @@
#define offsetof(TYPE, MEMBER) ((size_t) &(((TYPE *) 0)->MEMBER))
#endif
#if defined (HAVE_FSEEKO64)
#define FSEEK_FUNC fseeko64
#elif defined (HAVE_FSEEKO)
#define FSEEK_FUNC fseeko
#else
#define FSEEK_FUNC fseek
#endif
typedef struct elf_section_list
{
Elf_Internal_Shdr * hdr;
@ -482,7 +490,7 @@ get_data (void *var,
return NULL;
}
if (fseek (filedata->handle, filedata->archive_file_offset + offset,
if (FSEEK_FUNC (filedata->handle, filedata->archive_file_offset + offset,
SEEK_SET))
{
if (reason)
@ -6283,7 +6291,7 @@ the .dynamic section is not the same as the dynamic segment\n"));
if (segment->p_offset >= filedata->file_size
|| segment->p_filesz > filedata->file_size - segment->p_offset
|| segment->p_filesz - 1 >= (size_t) -2
|| fseek (filedata->handle,
|| FSEEK_FUNC (filedata->handle,
filedata->archive_file_offset + (long) segment->p_offset,
SEEK_SET))
error (_("Unable to find program interpreter name\n"));
@ -11056,7 +11064,7 @@ get_num_dynamic_syms (Filedata * filedata)
&& filedata->file_header.e_ident[EI_CLASS] == ELFCLASS64)
hash_ent_size = 8;
if (fseek (filedata->handle,
if (FSEEK_FUNC (filedata->handle,
(filedata->archive_file_offset
+ offset_from_vma (filedata, filedata->dynamic_info[DT_HASH],
sizeof nb + sizeof nc)),
@ -11109,7 +11117,7 @@ get_num_dynamic_syms (Filedata * filedata)
uint64_t buckets_vma;
unsigned long hn;
if (fseek (filedata->handle,
if (FSEEK_FUNC (filedata->handle,
(filedata->archive_file_offset
+ offset_from_vma (filedata,
filedata->dynamic_info_DT_GNU_HASH,
@ -11135,7 +11143,7 @@ get_num_dynamic_syms (Filedata * filedata)
else
buckets_vma += bitmaskwords * 8;
if (fseek (filedata->handle,
if (FSEEK_FUNC (filedata->handle,
(filedata->archive_file_offset
+ offset_from_vma (filedata, buckets_vma, 4)),
SEEK_SET))
@ -11165,7 +11173,7 @@ get_num_dynamic_syms (Filedata * filedata)
maxchain -= filedata->gnusymidx;
if (fseek (filedata->handle,
if (FSEEK_FUNC (filedata->handle,
(filedata->archive_file_offset
+ offset_from_vma (filedata,
buckets_vma + 4 * (filedata->ngnubuckets
@ -11192,7 +11200,7 @@ get_num_dynamic_syms (Filedata * filedata)
}
while ((byte_get (nb, 4) & 1) == 0);
if (fseek (filedata->handle,
if (FSEEK_FUNC (filedata->handle,
(filedata->archive_file_offset
+ offset_from_vma (filedata, (buckets_vma
+ 4 * filedata->ngnubuckets),
@ -11211,7 +11219,7 @@ get_num_dynamic_syms (Filedata * filedata)
if (filedata->dynamic_info_DT_MIPS_XHASH)
{
if (fseek (filedata->handle,
if (FSEEK_FUNC (filedata->handle,
(filedata->archive_file_offset
+ offset_from_vma (filedata, (buckets_vma
+ 4 * (filedata->ngnubuckets
@ -22610,7 +22618,7 @@ process_archive (Filedata * filedata, bool is_thin_archive)
ret = false;
}
if (fseek (filedata->handle, current_pos, SEEK_SET) != 0)
if (FSEEK_FUNC (filedata->handle, current_pos, SEEK_SET) != 0)
{
error (_("%s: failed to seek back to start of object files "
"in the archive\n"),
@ -22637,7 +22645,7 @@ process_archive (Filedata * filedata, bool is_thin_archive)
char * qualified_name;
/* Read the next archive header. */
if (fseek (filedata->handle, arch.next_arhdr_offset, SEEK_SET) != 0)
if (FSEEK_FUNC (filedata->handle, arch.next_arhdr_offset, SEEK_SET) != 0)
{
error (_("%s: failed to seek to next archive header\n"),
arch.file_name);
@ -22747,7 +22755,7 @@ process_archive (Filedata * filedata, bool is_thin_archive)
/* The nested archive file will have been opened and setup by
get_archive_member_name. */
if (fseek (nested_arch.file, filedata->archive_file_offset,
if (FSEEK_FUNC (nested_arch.file, filedata->archive_file_offset,
SEEK_SET) != 0)
{
error (_("%s: failed to seek to archive member.\n"),