From 9b32cba44ddeb32251092a05f1238d2462eb2345 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Mon, 8 Jul 2019 13:59:15 +0100 Subject: [PATCH] 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. --- binutils/ChangeLog | 5 ++ binutils/objdump.c | 7 +-- binutils/readelf.c | 7 +-- libctf/ChangeLog | 9 ++++ libctf/ctf-dump.c | 129 ++++++++++++++++++++++++++++++++++++++++++++- libctf/ctf-impl.h | 1 + libctf/ctf-open.c | 7 +-- 7 files changed, 151 insertions(+), 14 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index f4402ae7423..356eb0592be 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Nick Alcock + + * objdump.c (dump_ctf_archive_member): Dump the CTF header. + * readelf.c (dump_section_as_ctf): Likewise. + 2019-10-02 Niklas Gürtler PR 24942 diff --git a/binutils/objdump.c b/binutils/objdump.c index 96727a0f51e..d5a45ae5cb9 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -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; diff --git a/binutils/readelf.c b/binutils/readelf.c index 0962877ad8f..7e2b3adcf7b 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -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; diff --git a/libctf/ChangeLog b/libctf/ChangeLog index 9188a25c7f2..d0d0d6785c1 100644 --- a/libctf/ChangeLog +++ b/libctf/ChangeLog @@ -1,3 +1,12 @@ +2019-07-08 Nick Alcock + + * 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 * ctf-impl.h (ctf_file_t): New fields ctf_header, ctf_dynbase, diff --git a/libctf/ctf-dump.c b/libctf/ctf-dump.c index 0e8ab202dd8..acb882ba53a 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 1cfab431cac..5b331cbc6d2 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 ec05ce59cd5..2979ef8d287 100644 --- a/libctf/ctf-open.c +++ b/libctf/ctf-open.c @@ -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", -- 2.30.2