diff options
-rw-r--r-- | binutils/ChangeLog | 10 | ||||
-rw-r--r-- | binutils/readelf.c | 110 | ||||
-rw-r--r-- | include/ChangeLog | 4 | ||||
-rw-r--r-- | include/ctf-api.h | 4 | ||||
-rw-r--r-- | libctf/ChangeLog | 12 | ||||
-rw-r--r-- | libctf/ctf-archive.c | 76 | ||||
-rw-r--r-- | libctf/ctf-impl.h | 6 | ||||
-rw-r--r-- | libctf/ctf-open-bfd.c | 68 | ||||
-rw-r--r-- | libctf/libctf.ver | 1 |
9 files changed, 182 insertions, 109 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 1532a37..95a868a 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,5 +1,15 @@ 2020-06-26 Nick Alcock <nick.alcock@oracle.com> + * readelf.c (dump_section_as_ctf): Support .ctf archives using + ctf_arc_bufopen. Automatically load the .ctf member of such + archives as the parent of all other members, unless specifically + overridden via --ctf-parent. Split out dumping code into... + (dump_ctf_archive_member): ... here, as in objdump, and call + it once per archive member. + (dump_ctf_indent_lines): Code style fix. + +2020-06-26 Nick Alcock <nick.alcock@oracle.com> + * configure.ac [--enable-libctf]: New, default yes. Set ENABLE_LIBCTF accordingly. * Makefile.am [!ENABLE_LIBCTF]: Empty LIBCTF and LIBCTF_NOBFD. diff --git a/binutils/readelf.c b/binutils/readelf.c index 2f0cd77..1d7cfbc 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -14151,8 +14151,9 @@ shdr_to_ctf_sect (ctf_sect_t *buf, Elf_Internal_Shdr *shdr, Filedata *filedata) it is passed, or a pointer to newly-allocated storage, in which case dump_ctf() will free it when it no longer needs it. */ -static char *dump_ctf_indent_lines (ctf_sect_names_t sect ATTRIBUTE_UNUSED, - char *s, void *arg) +static char * +dump_ctf_indent_lines (ctf_sect_names_t sect ATTRIBUTE_UNUSED, + char *s, void *arg) { const char *blanks = arg; char *new_s; @@ -14162,6 +14163,55 @@ static char *dump_ctf_indent_lines (ctf_sect_names_t sect ATTRIBUTE_UNUSED, return new_s; } +/* Dump one CTF archive member. */ + +static int +dump_ctf_archive_member (ctf_file_t *ctf, const char *name, void *arg) +{ + ctf_file_t *parent = (ctf_file_t *) arg; + const char *things[] = {"Header", "Labels", "Data objects", + "Function objects", "Variables", "Types", "Strings", + ""}; + const char **thing; + size_t i; + + /* Only print out the name of non-default-named archive members. + The name .ctf appears everywhere, even for things that aren't + really archives, so printing it out is liable to be confusing. + + The parent, if there is one, is the default-owned archive member: + avoid importing it into itself. (This does no harm, but looks + confusing.) */ + + if (strcmp (name, ".ctf") != 0) + { + printf (_("\nCTF archive member: %s:\n"), name); + ctf_import (ctf, parent); + } + + for (i = 0, thing = things; *thing[0]; thing++, i++) + { + ctf_dump_state_t *s = NULL; + char *item; + + printf ("\n %s:\n", *thing); + while ((item = ctf_dump (ctf, &s, i, dump_ctf_indent_lines, + (void *) " ")) != NULL) + { + printf ("%s\n", item); + free (item); + } + + if (ctf_errno (ctf)) + { + error (_("Iteration failed: %s, %s\n"), *thing, + ctf_errmsg (ctf_errno (ctf))); + return 1; + } + } + return 0; +} + static bfd_boolean dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata) { @@ -14175,16 +14225,12 @@ dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata) ctf_sect_t ctfsect, symsect, strsect, parentsect; ctf_sect_t * symsectp = NULL; ctf_sect_t * strsectp = NULL; - ctf_file_t * ctf = NULL; - ctf_file_t * parent = NULL; + ctf_archive_t * ctfa = NULL; + ctf_archive_t * parenta = NULL, *lookparent; + ctf_file_t * parent = NULL; - const char *things[] = {"Header", "Labels", "Data objects", - "Function objects", "Variables", "Types", "Strings", - ""}; - const char **thing; int err; bfd_boolean ret = FALSE; - size_t i; shdr_to_ctf_sect (&ctfsect, section, filedata); data = get_section_contents (section, filedata); @@ -14243,9 +14289,11 @@ dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata) parentsect.cts_data = parentdata; } - /* Load the CTF file and dump it. */ + /* Load the CTF file and dump it. It may be a raw CTF section, or an archive: + libctf papers over the difference, so we can pretend it is always an + archive. Possibly open the parent as well, if one was specified. */ - if ((ctf = ctf_bufopen (&ctfsect, symsectp, strsectp, &err)) == NULL) + if ((ctfa = ctf_arc_bufopen (&ctfsect, symsectp, strsectp, &err)) == NULL) { error (_("CTF open failure: %s\n"), ctf_errmsg (err)); goto fail; @@ -14253,13 +14301,24 @@ dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata) if (parentdata) { - if ((parent = ctf_bufopen (&parentsect, symsectp, strsectp, &err)) == NULL) + if ((parenta = ctf_arc_bufopen (&parentsect, symsectp, strsectp, + &err)) == NULL) { error (_("CTF open failure: %s\n"), ctf_errmsg (err)); goto fail; } + lookparent = parenta; + } + else + lookparent = ctfa; - ctf_import (ctf, parent); + /* Assume that the applicable parent archive member is the default one. + (This is what all known implementations are expected to do, if they + put CTFs and their parents in archives together.) */ + if ((parent = ctf_arc_open_by_name (lookparent, NULL, &err)) == NULL) + { + error (_("CTF open failure: %s\n"), ctf_errmsg (err)); + goto fail; } ret = TRUE; @@ -14267,30 +14326,13 @@ dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata) printf (_("\nDump of CTF section '%s':\n"), printable_section_name (filedata, section)); - for (i = 0, thing = things; *thing[0]; thing++, i++) - { - ctf_dump_state_t *s = NULL; - char *item; - - printf ("\n %s:\n", *thing); - while ((item = ctf_dump (ctf, &s, i, dump_ctf_indent_lines, - (void *) " ")) != NULL) - { - printf ("%s\n", item); - free (item); - } - - if (ctf_errno (ctf)) - { - error (_("Iteration failed: %s, %s\n"), *thing, - ctf_errmsg (ctf_errno (ctf))); - ret = FALSE; - } - } + if (ctf_archive_iter (ctfa, dump_ctf_archive_member, parent) != 0) + ret = FALSE; fail: - ctf_file_close (ctf); ctf_file_close (parent); + ctf_close (ctfa); + ctf_close (parenta); free (parentdata); free (data); free (symdata); diff --git a/include/ChangeLog b/include/ChangeLog index ab6d753..dc7089e 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2020-06-26 Nick Alcock <nick.alcock@oracle.com> + + * ctf-api.h (ctf_arc_bufopen): New. + 2020-06-26 Pat Bernardi <bernardi@adacore.com> * elf/m68k.h: Add enum for GNU object attribute with floating point diff --git a/include/ctf-api.h b/include/ctf-api.h index efc4989..d6b05bc 100644 --- a/include/ctf-api.h +++ b/include/ctf-api.h @@ -263,6 +263,10 @@ extern void ctf_close (ctf_archive_t *); extern ctf_sect_t ctf_getdatasect (const ctf_file_t *); extern ctf_archive_t *ctf_get_arc (const ctf_file_t *); extern ctf_archive_t *ctf_arc_open (const char *, int *); +extern ctf_archive_t *ctf_arc_bufopen (const ctf_sect_t *, + const ctf_sect_t *, + const ctf_sect_t *, + int *); extern void ctf_arc_close (ctf_archive_t *); extern ctf_file_t *ctf_arc_open_by_name (const ctf_archive_t *, const char *, int *); diff --git a/libctf/ChangeLog b/libctf/ChangeLog index 3ab0a6c..5e473a7 100644 --- a/libctf/ChangeLog +++ b/libctf/ChangeLog @@ -1,5 +1,17 @@ 2020-06-26 Nick Alcock <nick.alcock@oracle.com> + * ctf-impl.h (ctf_new_archive_internal): Declare. + (ctf_arc_bufopen): Remove. + (ctf_archive_internal) <ctfi_free_symsect>: New. + * ctf-archive.c (ctf_arc_close): Use it. + (ctf_arc_bufopen): Fuse into... + (ctf_new_archive_internal): ... this, moved across from... + * ctf-open-bfd.c: ... here. + (ctf_bfdopen_ctfsect): Use ctf_arc_bufopen. + * libctf.ver: Add it. + +2020-06-26 Nick Alcock <nick.alcock@oracle.com> + * ctf-create.c (ctf_add_forward): Intern in the right namespace. (ctf_dtd_delete): Remove correspondingly. (ctf_rollback): Likewise. diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c index 73d772f..d27b27e 100644 --- a/libctf/ctf-archive.c +++ b/libctf/ctf-archive.c @@ -343,21 +343,71 @@ search_modent_by_name (const void *key, const void *ent) return strcmp (k, &search_nametbl[le64toh (v->name_offset)]); } -/* A trivial wrapper: open a CTF archive, from data in a buffer (which the - caller must preserve until ctf_arc_close() time). Returns the archive, or - NULL and an error in *err (if not NULL). */ -struct ctf_archive * -ctf_arc_bufopen (const void *buf, size_t size _libctf_unused_, int *errp) +/* 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. */ + +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) { - struct ctf_archive *arc = (struct ctf_archive *) buf; + struct ctf_archive_internal *arci; - if (le64toh (arc->ctfa_magic) != CTFA_MAGIC) + if ((arci = calloc (1, sizeof (struct ctf_archive_internal))) == NULL) { - if (errp) - *errp = ECTF_FMT; - return NULL; + if (is_archive) + ctf_arc_close_internal (arc); + else + ctf_file_close (fp); + return (ctf_set_open_errno (errp, errno)); } - return arc; + arci->ctfi_is_archive = is_archive; + if (is_archive) + arci->ctfi_archive = arc; + else + arci->ctfi_file = fp; + if (symsect) + memcpy (&arci->ctfi_symsect, symsect, sizeof (struct ctf_sect)); + if (strsect) + memcpy (&arci->ctfi_strsect, strsect, sizeof (struct ctf_sect)); + arci->ctfi_free_symsect = 0; + + return arci; +} + +/* Open a CTF archive or dictionary from data in a buffer (which the caller must + preserve until ctf_arc_close() time). Returns the archive, or NULL and an + error in *err (if not NULL). */ +ctf_archive_t * +ctf_arc_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, + const ctf_sect_t *strsect, int *errp) +{ + struct ctf_archive *arc = NULL; + int is_archive; + ctf_file_t *fp = NULL; + + if (ctfsect->cts_size > sizeof (uint64_t) && + ((*(uint64_t *) ctfsect->cts_data) == CTFA_MAGIC)) + { + /* The archive is mmappable, so this operation is trivial. */ + + is_archive = 1; + arc = (struct ctf_archive *) ctfsect->cts_data; + } + else + { + is_archive = 0; + if ((fp = ctf_bufopen (ctfsect, symsect, strsect, errp)) == NULL) + { + ctf_dprintf ("ctf_internal_open(): cannot open CTF: %s\n", + ctf_errmsg (*errp)); + return NULL; + } + } + return ctf_new_archive_internal (is_archive, arc, fp, symsect, strsect, + errp); } /* Open a CTF archive. Returns the archive, or NULL and an error in *err (if @@ -436,8 +486,8 @@ ctf_arc_close (ctf_archive_t *arc) ctf_arc_close_internal (arc->ctfi_archive); else ctf_file_close (arc->ctfi_file); - free ((void *) arc->ctfi_symsect.cts_data); - /* Do not free the ctfi_strsect: it is bound to the bfd. */ + if (arc->ctfi_free_symsect) + free ((void *) arc->ctfi_symsect.cts_data); free (arc->ctfi_data); if (arc->ctfi_bfd_close) arc->ctfi_bfd_close (arc); diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h index 56ef9a3..ade1a6e 100644 --- a/libctf/ctf-impl.h +++ b/libctf/ctf-impl.h @@ -309,6 +309,7 @@ struct ctf_archive_internal struct ctf_archive *ctfi_archive; ctf_sect_t ctfi_symsect; ctf_sect_t ctfi_strsect; + int ctfi_free_symsect; void *ctfi_data; bfd *ctfi_abfd; /* Optional source of section data. */ void (*ctfi_bfd_close) (struct ctf_archive_internal *); @@ -435,8 +436,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 *ctf_arc_open_internal (const char *, int *); -extern struct ctf_archive *ctf_arc_bufopen (const void *, size_t, int *); extern void ctf_arc_close_internal (struct ctf_archive *); extern void *ctf_set_open_errno (int *, int); extern unsigned long ctf_set_errno (ctf_file_t *, int); diff --git a/libctf/ctf-open-bfd.c b/libctf/ctf-open-bfd.c index 24c0403..630a158 100644 --- a/libctf/ctf-open-bfd.c +++ b/libctf/ctf-open-bfd.c @@ -32,40 +32,6 @@ #include "elf-bfd.h" -/* 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 (though the STRSECT interior is bound to the bfd - * and is not actually freed by this machinery). */ - -static 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) -{ - struct ctf_archive_internal *arci; - - if ((arci = calloc (1, sizeof (struct ctf_archive_internal))) == NULL) - { - if (is_archive) - ctf_arc_close_internal (arc); - else - ctf_file_close (fp); - return (ctf_set_open_errno (errp, errno)); - } - arci->ctfi_is_archive = is_archive; - if (is_archive) - arci->ctfi_archive = arc; - else - arci->ctfi_file = fp; - if (symsect) - memcpy (&arci->ctfi_symsect, symsect, sizeof (struct ctf_sect)); - if (strsect) - memcpy (&arci->ctfi_strsect, strsect, sizeof (struct ctf_sect)); - - return arci; -} - /* Free the BFD bits of a CTF file on ctf_arc_close(). */ static void @@ -107,6 +73,7 @@ ctf_bfdopen (struct bfd *abfd, int *errp) if ((arc = ctf_bfdopen_ctfsect (abfd, &ctfsect, errp)) != NULL) { + /* This frees the cts_data later. */ arc->ctfi_data = (void *) ctfsect.cts_data; return arc; } @@ -116,20 +83,16 @@ ctf_bfdopen (struct bfd *abfd, int *errp) } /* Open a CTF file given the specified BFD and CTF section (which may contain a - CTF archive or a file). Takes ownership of the ctfsect, and frees it - later. */ + CTF archive or a file). */ ctf_archive_t * ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, const ctf_sect_t *ctfsect, int *errp) { - struct ctf_archive *arc = NULL; ctf_archive_t *arci; - ctf_file_t *fp = NULL; ctf_sect_t *symsectp = NULL; ctf_sect_t *strsectp = NULL; const char *bfderrstr = NULL; - int is_archive; #ifdef HAVE_BFD_ELF ctf_sect_t symsect, strsect; @@ -192,30 +155,13 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, } #endif - if (ctfsect->cts_size > sizeof (uint64_t) && - ((*(uint64_t *) ctfsect->cts_data) == CTFA_MAGIC)) - { - is_archive = 1; - if ((arc = ctf_arc_bufopen ((void *) ctfsect->cts_data, - ctfsect->cts_size, errp)) == NULL) - goto err_free_str; - } - else + arci = ctf_arc_bufopen (ctfsect, symsectp, strsectp, errp); + if (arci) { - is_archive = 0; - if ((fp = ctf_bufopen (ctfsect, symsectp, strsectp, errp)) == NULL) - { - ctf_dprintf ("ctf_internal_open(): cannot open CTF: %s\n", - ctf_errmsg (*errp)); - goto err_free_str; - } + /* Request freeing of the symsect. */ + arci->ctfi_free_symsect = 1; + return arci; } - arci = ctf_new_archive_internal (is_archive, arc, fp, symsectp, strsectp, - errp); - - if (arci) - return arci; - err_free_str: ; #ifdef HAVE_BFD_ELF err_free_sym: free (symtab); diff --git a/libctf/libctf.ver b/libctf/libctf.ver index 14ca413..aad304b 100644 --- a/libctf/libctf.ver +++ b/libctf/libctf.ver @@ -128,6 +128,7 @@ LIBCTF_1.0 { ctf_arc_write; ctf_arc_write_fd; ctf_arc_open; + ctf_arc_bufopen; ctf_arc_close; ctf_arc_open_by_name; ctf_arc_open_by_name_sections; |