bfd_get_size cache

We have calls to bfd_get_size when swapping in ELF section headers.
Since object files can have a large number of sections, it's worth
caching the file size rather than making lots of stat system calls.

	* bfd.c (struct bfd): Move format and direction to other
	bitfields.  Add "size".
	* bfdio.c (bfd_get_size): Cache size when not writing file.
	* opncls.c (bfd_get_debug_link_info_1): Allow for bfd_get_size
	returning zero, ie. unknown.
	(bfd_get_alt_debug_link_info): Likewise.
	* bfd-in2.h: Regenerate.
This commit is contained in:
Alan Modra 2020-02-19 13:14:28 +10:30
parent 7c5fa58ea9
commit b03202e32c
5 changed files with 59 additions and 20 deletions

View file

@ -1,3 +1,13 @@
2020-02-19 Alan Modra <amodra@gmail.com>
* bfd.c (struct bfd): Move format and direction to other
bitfields. Add "size".
* bfdio.c (bfd_get_size): Cache size when not writing file.
* opncls.c (bfd_get_debug_link_info_1): Allow for bfd_get_size
returning zero, ie. unknown.
(bfd_get_alt_debug_link_info): Likewise.
* bfd-in2.h: Regenerate.
2020-02-19 Alan Modra <amodra@gmail.com> 2020-02-19 Alan Modra <amodra@gmail.com>
* coffgen.c (_bfd_coff_get_external_symbols): Don't call * coffgen.c (_bfd_coff_get_external_symbols): Don't call

View file

@ -6497,12 +6497,6 @@ struct bfd
/* A unique identifier of the BFD */ /* A unique identifier of the BFD */
unsigned int id; unsigned int id;
/* The format which belongs to the BFD. (object, core, etc.) */
ENUM_BITFIELD (bfd_format) format : 3;
/* The direction with which the BFD was opened. */
ENUM_BITFIELD (bfd_direction) direction : 2;
/* Format_specific flags. */ /* Format_specific flags. */
flagword flags; flagword flags;
@ -6606,6 +6600,12 @@ struct bfd
| BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT \ | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT \
| BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON) | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON)
/* The format which belongs to the BFD. (object, core, etc.) */
ENUM_BITFIELD (bfd_format) format : 3;
/* The direction with which the BFD was opened. */
ENUM_BITFIELD (bfd_direction) direction : 2;
/* Is the file descriptor being cached? That is, can it be closed as /* Is the file descriptor being cached? That is, can it be closed as
needed, and re-opened when accessed later? */ needed, and re-opened when accessed later? */
unsigned int cacheable : 1; unsigned int cacheable : 1;
@ -6706,6 +6706,11 @@ struct bfd
/* Pointer to structure which contains architecture information. */ /* Pointer to structure which contains architecture information. */
const struct bfd_arch_info *arch_info; const struct bfd_arch_info *arch_info;
/* Cached length of file for bfd_get_size. 0 until bfd_get_size is
called, 1 if stat returns an error or the file size is too large to
return in ufile_ptr. Both 0 and 1 should be treated as "unknown". */
ufile_ptr size;
/* Stuff only useful for archives. */ /* Stuff only useful for archives. */
void *arelt_data; void *arelt_data;
struct bfd *my_archive; /* The containing archive BFD. */ struct bfd *my_archive; /* The containing archive BFD. */

View file

@ -85,12 +85,6 @@ CODE_FRAGMENT
. {* A unique identifier of the BFD *} . {* A unique identifier of the BFD *}
. unsigned int id; . unsigned int id;
. .
. {* The format which belongs to the BFD. (object, core, etc.) *}
. ENUM_BITFIELD (bfd_format) format : 3;
.
. {* The direction with which the BFD was opened. *}
. ENUM_BITFIELD (bfd_direction) direction : 2;
.
. {* Format_specific flags. *} . {* Format_specific flags. *}
. flagword flags; . flagword flags;
. .
@ -194,6 +188,12 @@ CODE_FRAGMENT
. | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT \ . | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT \
. | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON) . | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON)
. .
. {* The format which belongs to the BFD. (object, core, etc.) *}
. ENUM_BITFIELD (bfd_format) format : 3;
.
. {* The direction with which the BFD was opened. *}
. ENUM_BITFIELD (bfd_direction) direction : 2;
.
. {* Is the file descriptor being cached? That is, can it be closed as . {* Is the file descriptor being cached? That is, can it be closed as
. needed, and re-opened when accessed later? *} . needed, and re-opened when accessed later? *}
. unsigned int cacheable : 1; . unsigned int cacheable : 1;
@ -294,6 +294,11 @@ CODE_FRAGMENT
. {* Pointer to structure which contains architecture information. *} . {* Pointer to structure which contains architecture information. *}
. const struct bfd_arch_info *arch_info; . const struct bfd_arch_info *arch_info;
. .
. {* Cached length of file for bfd_get_size. 0 until bfd_get_size is
. called, 1 if stat returns an error or the file size is too large to
. return in ufile_ptr. Both 0 and 1 should be treated as "unknown". *}
. ufile_ptr size;
.
. {* Stuff only useful for archives. *} . {* Stuff only useful for archives. *}
. void *arelt_data; . void *arelt_data;
. struct bfd *my_archive; {* The containing archive BFD. *} . struct bfd *my_archive; {* The containing archive BFD. *}

View file

@ -415,17 +415,32 @@ DESCRIPTION
of space for the 15 bazillon byte table it is about to read. of space for the 15 bazillon byte table it is about to read.
This function at least allows us to answer the question, "is the This function at least allows us to answer the question, "is the
size reasonable?". size reasonable?".
A return value of zero indicates the file size is unknown.
*/ */
ufile_ptr ufile_ptr
bfd_get_size (bfd *abfd) bfd_get_size (bfd *abfd)
{
/* A size of 0 means we haven't yet called bfd_stat. A size of 1
means we have a cached value of 0, ie. unknown. */
if (abfd->size <= 1 || bfd_write_p (abfd))
{ {
struct stat buf; struct stat buf;
if (bfd_stat (abfd, &buf) != 0) if (abfd->size == 1 && !bfd_write_p (abfd))
return 0; return 0;
return buf.st_size; if (bfd_stat (abfd, &buf) != 0
|| buf.st_size == 0
|| buf.st_size - (ufile_ptr) buf.st_size != 0)
{
abfd->size = 1;
return 0;
}
abfd->size = buf.st_size;
}
return abfd->size;
} }
/* /*

View file

@ -1209,6 +1209,7 @@ bfd_get_debug_link_info_1 (bfd *abfd, void *crc32_out)
unsigned int crc_offset; unsigned int crc_offset;
char *name; char *name;
bfd_size_type size; bfd_size_type size;
ufile_ptr file_size;
BFD_ASSERT (abfd); BFD_ASSERT (abfd);
BFD_ASSERT (crc32_out); BFD_ASSERT (crc32_out);
@ -1219,9 +1220,10 @@ bfd_get_debug_link_info_1 (bfd *abfd, void *crc32_out)
return NULL; return NULL;
size = bfd_section_size (sect); size = bfd_section_size (sect);
file_size = bfd_get_size (abfd);
/* PR 22794: Make sure that the section has a reasonable size. */ /* PR 22794: Make sure that the section has a reasonable size. */
if (size < 8 || size >= bfd_get_size (abfd)) if (size < 8 || (file_size != 0 && size >= file_size))
return NULL; return NULL;
if (!bfd_malloc_and_get_section (abfd, sect, &contents)) if (!bfd_malloc_and_get_section (abfd, sect, &contents))
@ -1298,6 +1300,7 @@ bfd_get_alt_debug_link_info (bfd * abfd, bfd_size_type *buildid_len,
unsigned int buildid_offset; unsigned int buildid_offset;
char *name; char *name;
bfd_size_type size; bfd_size_type size;
ufile_ptr file_size;
BFD_ASSERT (abfd); BFD_ASSERT (abfd);
BFD_ASSERT (buildid_len); BFD_ASSERT (buildid_len);
@ -1309,7 +1312,8 @@ bfd_get_alt_debug_link_info (bfd * abfd, bfd_size_type *buildid_len,
return NULL; return NULL;
size = bfd_section_size (sect); size = bfd_section_size (sect);
if (size < 8 || size >= bfd_get_size (abfd)) file_size = bfd_get_size (abfd);
if (size < 8 || (file_size != 0 && size >= file_size))
return NULL; return NULL;
if (!bfd_malloc_and_get_section (abfd, sect, & contents)) if (!bfd_malloc_and_get_section (abfd, sect, & contents))