libctf: adjust dumper for symtypetab changes

Now that we have a new format for the function info section, it's much
easier to dump it: we can use the same code we use for the object type
section, and that's got simpler too because we can use ctf_symbol_next.

Also dump the new stuff in the header: the new flags bits and the index
section lengths.

libctf/ChangeLog
2020-11-20  Nick Alcock  <nick.alcock@oracle.com>

	* ctf-dump.c (ctf_dump_header): Dump the new flags bits and the index
	section lengths.
	(ctf_dump_objts): Report indexed sections.  Also dump functions.  Use
	ctf_symbol_next, not manual looping.
	(ctf_dump_funcs): Delete.
	(ctf_dump): Use ctf_dump_objts, not ctf_dump_funcs.
This commit is contained in:
Nick Alcock 2020-11-20 13:34:04 +00:00
parent 1136c37971
commit 4665e895c3
2 changed files with 89 additions and 132 deletions

View file

@ -1,3 +1,12 @@
2020-11-20 Nick Alcock <nick.alcock@oracle.com>
* ctf-dump.c (ctf_dump_header): Dump the new flags bits and the index
section lengths.
(ctf_dump_objts): Report indexed sections. Also dump functions. Use
ctf_symbol_next, not manual looping.
(ctf_dump_funcs): Delete.
(ctf_dump): Use ctf_dump_objts, not ctf_dump_funcs.
2020-11-20 Nick Alcock <nick.alcock@oracle.com>
* ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New.

View file

@ -224,6 +224,7 @@ static int
ctf_dump_header (ctf_dict_t *fp, ctf_dump_state_t *state)
{
char *str;
char *flagstr = NULL;
const ctf_header_t *hp = fp->ctf_header;
const char *vertab[] =
{
@ -259,10 +260,29 @@ ctf_dump_header (ctf_dict_t *fp, ctf_dump_state_t *state)
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)
if (asprintf (&flagstr, "%s%s%s%s%s%s%s",
fp->ctf_openflags & CTF_F_COMPRESS
? "CTF_F_COMPRESS": "",
(fp->ctf_openflags & CTF_F_COMPRESS)
&& (fp->ctf_openflags & ~CTF_F_COMPRESS)
? ", " : "",
fp->ctf_openflags & CTF_F_NEWFUNCINFO
? "CTF_F_NEWFUNCINFO" : "",
(fp->ctf_openflags & (CTF_F_COMPRESS | CTF_F_NEWFUNCINFO))
&& (fp->ctf_openflags & ~(CTF_F_COMPRESS | CTF_F_NEWFUNCINFO))
? ", " : "",
fp->ctf_openflags & CTF_F_IDXSORTED
? "CTF_F_IDXSORTED" : "",
fp->ctf_openflags & (CTF_F_COMPRESS | CTF_F_NEWFUNCINFO
| CTF_F_IDXSORTED)
&& (fp->ctf_openflags & ~(CTF_F_COMPRESS | CTF_F_NEWFUNCINFO
| CTF_F_IDXSORTED))
? ", " : "",
fp->ctf_openflags & CTF_F_DYNSTR
? "CTF_F_DYNSTR" : "") < 0)
goto err;
if (asprintf (&str, "Flags: 0x%x (%s)", fp->ctf_openflags, flagstr) < 0)
goto err;
ctf_dump_append (state, str);
}
@ -287,7 +307,15 @@ ctf_dump_header (ctf_dict_t *fp, ctf_dump_state_t *state)
goto err;
if (ctf_dump_header_sectfield (fp, state, "Function info section",
hp->cth_funcoff, hp->cth_varoff) < 0)
hp->cth_funcoff, hp->cth_objtidxoff) < 0)
goto err;
if (ctf_dump_header_sectfield (fp, state, "Object index section",
hp->cth_objtidxoff, hp->cth_funcidxoff) < 0)
goto err;
if (ctf_dump_header_sectfield (fp, state, "Function index section",
hp->cth_funcidxoff, hp->cth_varoff) < 0)
goto err;
if (ctf_dump_header_sectfield (fp, state, "Variable section",
@ -304,6 +332,7 @@ ctf_dump_header (ctf_dict_t *fp, ctf_dump_state_t *state)
return 0;
err:
free (flagstr);
return (ctf_set_errno (fp, errno));
}
@ -334,149 +363,68 @@ ctf_dump_label (const char *name, const ctf_lblinfo_t *info,
return 0;
}
/* Dump all the object entries into the cds_items. (There is no iterator for
this section, so we just do it in a loop, and this function handles all of
them, rather than only one. */
/* Dump all the object or function entries into the cds_items. */
static int
ctf_dump_objts (ctf_dict_t *fp, ctf_dump_state_t *state)
ctf_dump_objts (ctf_dict_t *fp, ctf_dump_state_t *state, int functions)
{
size_t i;
const char *name;
ctf_id_t id;
ctf_next_t *i = NULL;
char *str = NULL;
for (i = 0; i < fp->ctf_nsyms; i++)
if ((functions && fp->ctf_funcidx_names)
|| (!functions && fp->ctf_objtidx_names))
str = str_append (str, _("Section is indexed.\n"));
else if (fp->ctf_symtab.cts_data == NULL)
str = str_append (str, _("No symbol table.\n"));
while ((id = ctf_symbol_next (fp, &i, &name, functions)) != CTF_ERR)
{
char *str;
char *typestr;
const char *sym_name;
ctf_id_t type;
char *typestr = NULL;
int err = 0;
if ((type = ctf_lookup_by_symbol (state->cds_fp, i)) == CTF_ERR)
switch (ctf_errno (state->cds_fp))
{
/* Most errors are just an indication that this symbol is not a data
symbol, but this one indicates that we were called wrong, on a
CTF file with no associated symbol table. */
case ECTF_NOSYMTAB:
return -1;
case ECTF_NOTDATA:
case ECTF_NOTYPEDAT:
continue;
}
/* Variable name. */
sym_name = ctf_lookup_symbol_name (fp, i);
if (sym_name[0] == '\0')
/* Emit the name, if we know it. */
if (name)
{
if (asprintf (&str, "%lx -> ", (unsigned long) i) < 0)
return (ctf_set_errno (fp, errno));
if (asprintf (&str, "%s -> ", name) < 0)
goto oom;
}
else
{
if (asprintf (&str, "%s (%lx) -> ", sym_name, (unsigned long) i) < 0)
return (ctf_set_errno (fp, errno));
}
str = xstrdup ("");
/* Variable type. */
if ((typestr = ctf_dump_format_type (state->cds_fp, type,
CTF_ADD_ROOT)) == NULL)
if ((typestr = ctf_type_aname (fp, id)) == NULL)
{
free (str);
return 0; /* Swallow the error. */
if (id == 0 || ctf_errno (fp) == ECTF_NONREPRESENTABLE)
{
if (asprintf (&typestr, " (%s)", _("type not represented in CTF")) < 0)
goto oom;
goto out;
}
if (asprintf (&typestr, ctf_errmsg (ctf_errno (fp))) < 0)
goto oom;
err = -1;
goto out;
}
str = str_append (str, typestr);
free (typestr);
ctf_dump_append (state, str);
}
return 0;
}
/* Dump all the function entries into the cds_items. (As above, there is no
iterator for this section.) */
static int
ctf_dump_funcs (ctf_dict_t *fp, ctf_dump_state_t *state)
{
size_t i;
for (i = 0; i < fp->ctf_nsyms; i++)
{
char *str;
char *bit = NULL;
const char *sym_name;
ctf_funcinfo_t fi;
ctf_id_t type;
if ((type = ctf_func_info (state->cds_fp, i, &fi)) == CTF_ERR)
switch (ctf_errno (state->cds_fp))
{
/* Most errors are just an indication that this symbol is not a data
symbol, but this one indicates that we were called wrong, on a
CTF file with no associated symbol table. */
case ECTF_NOSYMTAB:
return -1;
case ECTF_NOTDATA:
case ECTF_NOTFUNC:
case ECTF_NOFUNCDAT:
continue;
}
/* Return type and all args. */
if ((bit = ctf_type_aname (state->cds_fp, type)) == NULL)
{
ctf_err_warn (fp, 1, ctf_errno (state->cds_fp),
_("cannot look up return type dumping function type "
"for symbol 0x%li"), (unsigned long) i);
free (bit);
return -1; /* errno is set for us. */
}
/* Replace in the returned string, dropping in the function name. */
sym_name = ctf_lookup_symbol_name (fp, i);
if (sym_name[0] != '\0')
{
char *retstar;
char *new_bit;
char *walk;
new_bit = malloc (strlen (bit) + 1 + strlen (sym_name));
if (!new_bit)
goto oom;
/* See ctf_type_aname. */
retstar = strstr (bit, "(*) (");
if (!ctf_assert (fp, retstar))
goto assert_err;
retstar += 2; /* After the '*' */
/* C is not good at search-and-replace. */
walk = new_bit;
memcpy (walk, bit, retstar - bit);
walk += (retstar - bit);
strcpy (walk, sym_name);
walk += strlen (sym_name);
strcpy (walk, retstar);
free (bit);
bit = new_bit;
}
if (asprintf (&str, "Symbol 0x%lx: %s", (unsigned long) i, bit) < 0)
goto oom;
free (bit);
str = str_append (str, "\n");
ctf_dump_append (state, str);
continue;
oom:
free (bit);
return (ctf_set_errno (fp, errno));
assert_err:
free (bit);
return -1; /* errno is set for us. */
ctf_set_errno (fp, ENOMEM);
ctf_next_destroy (i);
return -1;
out:
str = str_append (str, typestr);
free (typestr);
ctf_dump_append (state, str);
ctf_next_destroy (i);
return err; /* errno is set for us. */
}
return 0;
}
@ -697,11 +645,11 @@ ctf_dump (ctf_dict_t *fp, ctf_dump_state_t **statep, ctf_sect_names_t sect,
}
break;
case CTF_SECT_OBJT:
if (ctf_dump_objts (fp, state) < 0)
if (ctf_dump_objts (fp, state, 0) < 0)
goto end; /* errno is set for us. */
break;
case CTF_SECT_FUNC:
if (ctf_dump_funcs (fp, state) < 0)
if (ctf_dump_objts (fp, state, 1) < 0)
goto end; /* errno is set for us. */
break;
case CTF_SECT_VAR: