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.
This commit is contained in:
Nick Alcock 2020-06-02 20:55:05 +01:00
parent 96e3ec2966
commit 601e455b75
4 changed files with 40 additions and 12 deletions

View file

@ -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);