libctf, binutils: dump the CTF header

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.)

v5: fix tabdamage.

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.
This commit is contained in:
Nick Alcock 2019-07-08 13:59:15 +01:00
parent fd55eae84d
commit 9b32cba44d
7 changed files with 151 additions and 14 deletions

View file

@ -1,3 +1,8 @@
2019-07-08 Nick Alcock <nick.alcock@oracle.com>
* objdump.c (dump_ctf_archive_member): Dump the CTF header.
* readelf.c (dump_section_as_ctf): Likewise.
2019-10-02 Niklas Gürtler <profclonk@gmail.com>
PR 24942

View file

@ -3282,8 +3282,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;
@ -3294,7 +3295,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;

View file

@ -13932,8 +13932,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;
@ -14014,7 +14015,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;

View file

@ -1,3 +1,12 @@
2019-07-08 Nick Alcock <nick.alcock@oracle.com>
* 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.
2019-07-06 Nick Alcock <nick.alcock@oracle.com>
* ctf-impl.h (ctf_file_t): New fields ctf_header, ctf_dynbase,

View file

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

View file

@ -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. */

View file

@ -1323,12 +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;
ctf_dprintf ("ctf_bufopen: uncompressed size=%lu\n",