[03/19] libctf, binutils: dump the CTF header

Message ID 20190716180420.236506-4-nick.alcock@oracle.com
State Superseded
Headers show
Series
  • CTF linking support
Related show

Commit Message

Nick Alcock July 16, 2019, 6:04 p.m.
The CTF header has before now been thrown away too soon to be dumped
using the ctf_dump() machinery used by objdump and readelf: instead, a
kludge involving debugging-priority dumps of the header offsets on every
open was used.

Replace this with proper first-class dumping machinery just like
everything else in the CTF file, and have objdump and readelf use it.
(The dumper already had an enum value in ctf_sect_names_t for this
purpose, waiting to be used.)

libctf/
	* ctf-impl.h (ctf_file_t): New field ctf_openflags.
	* ctf-open.c (ctf_bufopen): Set it.  No longer dump header offsets.
	* ctf-dump.c (dump_header): New function, dump the CTF header.
	(ctf_dump): Call it.
	(ctf_dump_header_strfield): New function.
	(ctf_dump_header_sectfield): Likewise.

binutils/
	* objdump.c (dump_ctf_archive_member): Dump the CTF header.
	* readelf.c (dump_section_as_ctf): Likewise.
---
 binutils/objdump.c |   7 +--
 binutils/readelf.c |   7 +--
 libctf/ctf-dump.c  | 129 ++++++++++++++++++++++++++++++++++++++++++++-
 libctf/ctf-impl.h  |   1 +
 libctf/ctf-open.c  |   6 +--
 5 files changed, 137 insertions(+), 13 deletions(-)

-- 
2.22.0.238.g049a27acdc

Patch

diff --git a/binutils/objdump.c b/binutils/objdump.c
index 6812ba7853..443dce806f 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -3255,8 +3255,9 @@  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[] = {"Labels", "Data objects", "Function objects",
-			  "Variables", "Types", "Strings", ""};
+  const char *things[] = {"Header", "Labels", "Data objects",
+                          "Function objects", "Variables", "Types", "Strings",
+                          ""};
   const char **thing;
   size_t i;
 
@@ -3267,7 +3268,7 @@  dump_ctf_archive_member (ctf_file_t *ctf, const char *name, void *arg)
     printf (_("\nCTF archive member: %s:\n"), sanitize_string (name));
 
   ctf_import (ctf, parent);
-  for (i = 1, thing = things; *thing[0]; thing++, i++)
+  for (i = 0, thing = things; *thing[0]; thing++, i++)
     {
       ctf_dump_state_t *s = NULL;
       char *item;
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 5e8fe824b3..ea35aeef5c 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -13872,8 +13872,9 @@  dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata)
   ctf_file_t *         ctf = NULL;
   ctf_file_t *         parent = NULL;
 
-  const char *things[] = {"Labels", "Data objects", "Function objects",
-			  "Variables", "Types", "Strings", ""};
+  const char *things[] = {"Header", "Labels", "Data objects",
+                          "Function objects", "Variables", "Types", "Strings",
+                          ""};
   const char **thing;
   int err;
   bfd_boolean ret = FALSE;
@@ -13954,7 +13955,7 @@  dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata)
   printf (_("\nDump of CTF section '%s':\n"),
 	  printable_section_name (filedata, section));
 
-  for (i = 1, thing = things; *thing[0]; thing++, i++)
+  for (i = 0, thing = things; *thing[0]; thing++, i++)
     {
       ctf_dump_state_t *s = NULL;
       char *item;
diff --git a/libctf/ctf-dump.c b/libctf/ctf-dump.c
index 0e8ab202dd..8c49a04afd 100644
--- a/libctf/ctf-dump.c
+++ b/libctf/ctf-dump.c
@@ -153,6 +153,132 @@  ctf_dump_format_type (ctf_file_t *fp, ctf_id_t id)
   return NULL;
 }
 
+/* Dump one string field from the file header into the cds_items.  */
+static int
+ctf_dump_header_strfield (ctf_file_t *fp, ctf_dump_state_t *state,
+			  const char *name, uint32_t value)
+{
+  char *str;
+  if (value)
+    {
+      if (asprintf (&str, "%s: %s\n", name, ctf_strptr (fp, value)) < 0)
+	goto err;
+      ctf_dump_append (state, str);
+    }
+  return 0;
+
+ err:
+  return (ctf_set_errno (fp, -ENOMEM));
+}
+
+/* Dump one section-offset field from the file header into the cds_items.  */
+static int
+ctf_dump_header_sectfield (ctf_file_t *fp, ctf_dump_state_t *state,
+			   const char *sect, uint32_t off, uint32_t nextoff)
+{
+  char *str;
+  if (nextoff - off)
+    {
+      if (asprintf (&str, "%s:\t0x%lx -- 0x%lx (0x%lx bytes)\n", sect,
+		    (unsigned long) off, (unsigned long) (nextoff - 1),
+		    (unsigned long) (nextoff - off)) < 0)
+	goto err;
+      ctf_dump_append (state, str);
+    }
+  return 0;
+
+ err:
+  return (ctf_set_errno (fp, -ENOMEM));
+}
+
+/* Dump the file header into the cds_items.  */
+static int
+ctf_dump_header (ctf_file_t *fp, ctf_dump_state_t *state)
+{
+  char *str;
+  const ctf_header_t *hp = fp->ctf_header;
+  const char *vertab[] =
+    {
+     NULL, "CTF_VERSION_1",
+     "CTF_VERSION_1_UPGRADED_3 (latest format, version 1 type "
+     "boundaries)",
+     "CTF_VERSION_2",
+     "CTF_VERSION_3", NULL
+    };
+  const char *verstr = NULL;
+
+  if (asprintf (&str, "Magic number: %x\n", hp->cth_magic) < 0)
+      goto err;
+  ctf_dump_append (state, str);
+
+  if (hp->cth_version <= CTF_VERSION)
+    verstr = vertab[hp->cth_version];
+
+  if (verstr == NULL)
+    verstr = "(not a valid version)";
+
+  if (asprintf (&str, "Version: %i (%s)\n", hp->cth_version,
+		verstr) < 0)
+    goto err;
+  ctf_dump_append (state, str);
+
+  /* Everything else is only printed if present.  */
+
+  /* The flags are unusual in that they represent the ctf_file_t *in memory*:
+     flags representing compression, etc, are turned off as the file is
+     decompressed.  So we store a copy of the flags before they are changed, for
+     the dumper.  */
+
+  if (fp->ctf_openflags > 0)
+    {
+      if (fp->ctf_openflags)
+	if (asprintf (&str, "Flags: 0x%x (%s)", fp->ctf_openflags,
+		      fp->ctf_openflags & CTF_F_COMPRESS ? "CTF_F_COMPRESS"
+		                                         : "") < 0)
+	goto err;
+      ctf_dump_append (state, str);
+    }
+
+  if (ctf_dump_header_strfield (fp, state, "Parent label",
+				hp->cth_parlabel) < 0)
+    goto err;
+
+  if (ctf_dump_header_strfield (fp, state, "Parent name", hp->cth_parname) < 0)
+    goto err;
+
+  if (ctf_dump_header_strfield (fp, state, "Compilation unit name",
+				hp->cth_cuname) < 0)
+    goto err;
+
+  if (ctf_dump_header_sectfield (fp, state, "Label section", hp->cth_lbloff,
+				 hp->cth_objtoff) < 0)
+    goto err;
+
+  if (ctf_dump_header_sectfield (fp, state, "Data object section",
+				 hp->cth_objtoff, hp->cth_funcoff) < 0)
+    goto err;
+
+  if (ctf_dump_header_sectfield (fp, state, "Function info section",
+				 hp->cth_funcoff, hp->cth_varoff) < 0)
+    goto err;
+
+  if (ctf_dump_header_sectfield (fp, state, "Variable section",
+				 hp->cth_varoff, hp->cth_typeoff) < 0)
+    goto err;
+
+  if (ctf_dump_header_sectfield (fp, state, "Type section",
+				 hp->cth_typeoff, hp->cth_stroff) < 0)
+    goto err;
+
+  if (ctf_dump_header_sectfield (fp, state, "String section", hp->cth_stroff,
+				 hp->cth_stroff + hp->cth_strlen + 1) < 0)
+    goto err;
+
+  return 0;
+ err:
+  return (ctf_set_errno (fp, -ENOMEM));
+}
+
 /* Dump a single label into the cds_items.  */
 
 static int
@@ -492,8 +618,7 @@  ctf_dump (ctf_file_t *fp, ctf_dump_state_t **statep, ctf_sect_names_t sect,
       switch (sect)
 	{
 	case CTF_SECT_HEADER:
-	  /* Nothing doable (yet): entire header is discarded after read-phase.  */
-	  str = strdup ("");
+	  ctf_dump_header (fp, state);
 	  break;
 	case CTF_SECT_LABEL:
 	  if (ctf_label_iter (fp, ctf_dump_label, state) < 0)
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index 1cfab431ca..5b331cbc6d 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -218,6 +218,7 @@  struct ctf_file
 {
   const ctf_fileops_t *ctf_fileops; /* Version-specific file operations.  */
   struct ctf_header *ctf_header;    /* The header from this CTF file.  */
+  unsigned char ctf_openflags;	    /* Flags the file had when opened.  */
   ctf_sect_t ctf_data;		    /* CTF data from object file.  */
   ctf_sect_t ctf_symtab;	    /* Symbol table from object file.  */
   ctf_sect_t ctf_strtab;	    /* String table from object file.  */
diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c
index 46fb42e1e3..5d070acd3f 100644
--- a/libctf/ctf-open.c
+++ b/libctf/ctf-open.c
@@ -1323,11 +1323,7 @@  ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
 
   if (foreign_endian)
     flip_header (hp);
-
-  ctf_dprintf ("header offsets: %x/%x/%x/%x/%x/%x/%x\n",
-	       hp->cth_lbloff, hp->cth_objtoff, hp->cth_funcoff,
-	       hp->cth_varoff, hp->cth_typeoff, hp->cth_stroff,
-               hp->cth_strlen);
+  fp->ctf_openflags = hp->cth_flags;
 
   fp->ctf_size = hp->cth_stroff + hp->cth_strlen;