aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Alcock <nick.alcock@oracle.com>2020-06-02 20:55:05 +0100
committerNick Alcock <nick.alcock@oracle.com>2020-07-22 17:57:33 +0100
commit601e455b758b7075d3027c030b9bd60f7b7face5 (patch)
tree655696f41764e9a7e7b6a5e76b5a87b52ffe6f42
parent96e3ec29664810995d6d7d3b6fd6ae2d19c532bd (diff)
downloadgdb-601e455b758b7075d3027c030b9bd60f7b7face5.zip
gdb-601e455b758b7075d3027c030b9bd60f7b7face5.tar.gz
gdb-601e455b758b7075d3027c030b9bd60f7b7face5.tar.bz2
libctf, archive: stop ctf_arc_bufopen triggering crazy unmaps
The archive machinery mmap()s its archives when possible: so it arranges to do appropriately-sized unmaps by recording the unmap length in the ctfa_magic value and unmapping that. This brilliant (horrible) trick works less well when ctf_arc_bufopen is called with an existing buffer (which might be a readonly mapping). ctf_arc_bufopen always returns a ctf_archive_t wrapper, so record in there the necessity to not unmap anything when a bufopen'ed archive is closed again. libctf/ * ctf-impl.h (struct ctf_archive_internal) <ctfi_unmap_on_close>: New. (ctf_new_archive_internal): Adjust. * ctf-archive.c (ctf_new_archive_internal): Likewise. Initialize ctfi_unmap_on_close. Adjust error path. (ctf_arc_bufopen): Adjust ctf_new_archive_internal call (unmap_on_close is 0). (ctf_arc_close): Only unmap if ctfi_unmap_on_close. * ctf-open-bfd.c (ctf_fdopen): Adjust.
-rw-r--r--libctf/ChangeLog12
-rw-r--r--libctf/ctf-archive.c26
-rw-r--r--libctf/ctf-impl.h10
-rw-r--r--libctf/ctf-open-bfd.c4
4 files changed, 40 insertions, 12 deletions
diff --git a/libctf/ChangeLog b/libctf/ChangeLog
index f0e2001..da28502 100644
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -1,5 +1,17 @@
2020-07-22 Nick Alcock <nick.alcock@oracle.com>
+ * ctf-impl.h (struct ctf_archive_internal)
+ <ctfi_unmap_on_close>: New.
+ (ctf_new_archive_internal): Adjust.
+ * ctf-archive.c (ctf_new_archive_internal): Likewise.
+ Initialize ctfi_unmap_on_close. Adjust error path.
+ (ctf_arc_bufopen): Adjust ctf_new_archive_internal call
+ (unmap_on_close is 0).
+ (ctf_arc_close): Only unmap if ctfi_unmap_on_close.
+ * ctf-open-bfd.c (ctf_fdopen): Adjust.
+
+2020-07-22 Nick Alcock <nick.alcock@oracle.com>
+
* ctf-types.c (ctf_type_aname): Return ECTF_CORRUPT if
ints, floats or typedefs have no name. Fix comment typo.
diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c
index d857c01..3c14d7d 100644
--- a/libctf/ctf-archive.c
+++ b/libctf/ctf-archive.c
@@ -336,10 +336,11 @@ search_modent_by_name (const void *key, const void *ent, void *arg)
/* Make a new struct ctf_archive_internal wrapper for a ctf_archive or a
ctf_file. Closes ARC and/or FP on error. Arrange to free the SYMSECT or
- STRSECT, as needed, on close. */
+ STRSECT, as needed, on close. Possibly do not unmap on close. */
struct ctf_archive_internal *
-ctf_new_archive_internal (int is_archive, struct ctf_archive *arc,
+ctf_new_archive_internal (int is_archive, int unmap_on_close,
+ struct ctf_archive *arc,
ctf_file_t *fp, const ctf_sect_t *symsect,
const ctf_sect_t *strsect,
int *errp)
@@ -349,7 +350,10 @@ ctf_new_archive_internal (int is_archive, struct ctf_archive *arc,
if ((arci = calloc (1, sizeof (struct ctf_archive_internal))) == NULL)
{
if (is_archive)
- ctf_arc_close_internal (arc);
+ {
+ if (unmap_on_close)
+ ctf_arc_close_internal (arc);
+ }
else
ctf_file_close (fp);
return (ctf_set_open_errno (errp, errno));
@@ -364,6 +368,7 @@ ctf_new_archive_internal (int is_archive, struct ctf_archive *arc,
if (strsect)
memcpy (&arci->ctfi_strsect, strsect, sizeof (struct ctf_sect));
arci->ctfi_free_symsect = 0;
+ arci->ctfi_unmap_on_close = unmap_on_close;
return arci;
}
@@ -382,7 +387,13 @@ ctf_arc_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
if (ctfsect->cts_size > sizeof (uint64_t) &&
((*(uint64_t *) ctfsect->cts_data) == CTFA_MAGIC))
{
- /* The archive is mmappable, so this operation is trivial. */
+ /* The archive is mmappable, so this operation is trivial.
+
+ This buffer is nonmodifiable, so the trick involving mmapping only part
+ of it and storing the length in the magic number is not applicable: so
+ record this fact in the archive-wrapper header. (We cannot record it
+ in the archive, because the archive may very well be a read-only
+ mapping.) */
is_archive = 1;
arc = (struct ctf_archive *) ctfsect->cts_data;
@@ -397,7 +408,7 @@ ctf_arc_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
return NULL;
}
}
- return ctf_new_archive_internal (is_archive, arc, fp, symsect, strsect,
+ return ctf_new_archive_internal (is_archive, 0, arc, fp, symsect, strsect,
errp);
}
@@ -474,7 +485,10 @@ ctf_arc_close (ctf_archive_t *arc)
return;
if (arc->ctfi_is_archive)
- ctf_arc_close_internal (arc->ctfi_archive);
+ {
+ if (arc->ctfi_unmap_on_close)
+ ctf_arc_close_internal (arc->ctfi_archive);
+ }
else
ctf_file_close (arc->ctfi_file);
if (arc->ctfi_free_symsect)
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index fdd48f0..4661aa8 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -312,6 +312,7 @@ struct ctf_file
struct ctf_archive_internal
{
int ctfi_is_archive;
+ int ctfi_unmap_on_close;
ctf_file_t *ctfi_file;
struct ctf_archive *ctfi_archive;
ctf_sect_t ctfi_symsect;
@@ -443,10 +444,11 @@ extern void ctf_str_rollback (ctf_file_t *, ctf_snapshot_id_t);
extern void ctf_str_purge_refs (ctf_file_t *);
extern ctf_strs_writable_t ctf_str_write_strtab (ctf_file_t *);
-extern struct ctf_archive_internal *ctf_new_archive_internal
- (int is_archive, struct ctf_archive *arc,
- ctf_file_t *fp, const ctf_sect_t *symsect,
- const ctf_sect_t *strsect, int *errp);
+extern struct ctf_archive_internal *
+ctf_new_archive_internal (int is_archive, int unmap_on_close,
+ struct ctf_archive *, ctf_file_t *,
+ const ctf_sect_t *symsect,
+ const ctf_sect_t *strsect, int *errp);
extern struct ctf_archive *ctf_arc_open_internal (const char *, int *);
extern void ctf_arc_close_internal (struct ctf_archive *);
extern void *ctf_set_open_errno (int *, int);
diff --git a/libctf/ctf-open-bfd.c b/libctf/ctf-open-bfd.c
index dafa265..2d2d572 100644
--- a/libctf/ctf-open-bfd.c
+++ b/libctf/ctf-open-bfd.c
@@ -230,7 +230,7 @@ ctf_fdopen (int fd, const char *filename, const char *target, int *errp)
fp->ctf_data_mmapped = data;
fp->ctf_data_mmapped_len = (size_t) st.st_size;
- return ctf_new_archive_internal (0, NULL, fp, NULL, NULL, errp);
+ return ctf_new_archive_internal (0, 1, NULL, fp, NULL, NULL, errp);
}
if ((nbytes = ctf_pread (fd, &arc_magic, sizeof (arc_magic), 0)) <= 0)
@@ -243,7 +243,7 @@ ctf_fdopen (int fd, const char *filename, const char *target, int *errp)
if ((arc = ctf_arc_open_internal (filename, errp)) == NULL)
return NULL; /* errno is set for us. */
- return ctf_new_archive_internal (1, arc, NULL, NULL, NULL, errp);
+ return ctf_new_archive_internal (1, 1, arc, NULL, NULL, NULL, errp);
}
/* Attempt to open the file with BFD. We must dup the fd first, since bfd