aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binutils/ChangeLog10
-rw-r--r--binutils/readelf.c110
-rw-r--r--include/ChangeLog4
-rw-r--r--include/ctf-api.h4
-rw-r--r--libctf/ChangeLog12
-rw-r--r--libctf/ctf-archive.c76
-rw-r--r--libctf/ctf-impl.h6
-rw-r--r--libctf/ctf-open-bfd.c68
-rw-r--r--libctf/libctf.ver1
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;