aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2020-02-19 13:14:28 +1030
committerAlan Modra <amodra@gmail.com>2020-02-19 13:14:28 +1030
commitb03202e32c8235997b3485b0b4655926ad97a1cc (patch)
tree0697dbbcfdd4c7b08d717ce5fcc5b640872e0367 /bfd
parent7c5fa58ea907c46817b915ec8b9b35a180e0e74c (diff)
downloadgdb-b03202e32c8235997b3485b0b4655926ad97a1cc.zip
gdb-b03202e32c8235997b3485b0b4655926ad97a1cc.tar.gz
gdb-b03202e32c8235997b3485b0b4655926ad97a1cc.tar.bz2
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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog10
-rw-r--r--bfd/bfd-in2.h19
-rw-r--r--bfd/bfd.c19
-rw-r--r--bfd/bfdio.c23
-rw-r--r--bfd/opncls.c8
5 files changed, 59 insertions, 20 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index fe2ffd3..58dbb56 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,15 @@
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>
+
* coffgen.c (_bfd_coff_get_external_symbols): Don't call
bfd_get_file_size twice.
(_bfd_coff_read_string_table): Allow for bfd_get_file_size
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 6b30f5f..2d56fda 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6497,12 +6497,6 @@ struct bfd
/* A unique identifier of the BFD */
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. */
flagword flags;
@@ -6606,6 +6600,12 @@ struct bfd
| BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT \
| 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
needed, and re-opened when accessed later? */
unsigned int cacheable : 1;
@@ -6695,7 +6695,7 @@ struct bfd
/* Symbol table for output BFD (with symcount entries).
Also used by the linker to cache input BFD symbols. */
- struct bfd_symbol **outsymbols;
+ struct bfd_symbol **outsymbols;
/* Used for input and output. */
unsigned int symcount;
@@ -6706,6 +6706,11 @@ struct bfd
/* Pointer to structure which contains architecture information. */
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. */
void *arelt_data;
struct bfd *my_archive; /* The containing archive BFD. */
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 574cebd..463f94b 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -85,12 +85,6 @@ CODE_FRAGMENT
. {* A unique identifier of the BFD *}
. 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. *}
. flagword flags;
.
@@ -194,6 +188,12 @@ CODE_FRAGMENT
. | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT \
. | 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
. needed, and re-opened when accessed later? *}
. unsigned int cacheable : 1;
@@ -283,7 +283,7 @@ CODE_FRAGMENT
.
. {* Symbol table for output BFD (with symcount entries).
. Also used by the linker to cache input BFD symbols. *}
-. struct bfd_symbol **outsymbols;
+. struct bfd_symbol **outsymbols;
.
. {* Used for input and output. *}
. unsigned int symcount;
@@ -294,6 +294,11 @@ CODE_FRAGMENT
. {* Pointer to structure which contains architecture information. *}
. 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. *}
. void *arelt_data;
. struct bfd *my_archive; {* The containing archive BFD. *}
diff --git a/bfd/bfdio.c b/bfd/bfdio.c
index fd81b93..49e0958 100644
--- a/bfd/bfdio.c
+++ b/bfd/bfdio.c
@@ -415,17 +415,32 @@ DESCRIPTION
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
size reasonable?".
+
+ A return value of zero indicates the file size is unknown.
*/
ufile_ptr
bfd_get_size (bfd *abfd)
{
- struct stat buf;
+ /* 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;
- if (bfd_stat (abfd, &buf) != 0)
- return 0;
+ if (abfd->size == 1 && !bfd_write_p (abfd))
+ 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;
}
/*
diff --git a/bfd/opncls.c b/bfd/opncls.c
index a03ad51..796202d 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -1209,6 +1209,7 @@ bfd_get_debug_link_info_1 (bfd *abfd, void *crc32_out)
unsigned int crc_offset;
char *name;
bfd_size_type size;
+ ufile_ptr file_size;
BFD_ASSERT (abfd);
BFD_ASSERT (crc32_out);
@@ -1219,9 +1220,10 @@ bfd_get_debug_link_info_1 (bfd *abfd, void *crc32_out)
return NULL;
size = bfd_section_size (sect);
+ file_size = bfd_get_size (abfd);
/* 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;
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;
char *name;
bfd_size_type size;
+ ufile_ptr file_size;
BFD_ASSERT (abfd);
BFD_ASSERT (buildid_len);
@@ -1309,7 +1312,8 @@ bfd_get_alt_debug_link_info (bfd * abfd, bfd_size_type *buildid_len,
return NULL;
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;
if (!bfd_malloc_and_get_section (abfd, sect, & contents))