aboutsummaryrefslogtreecommitdiff
path: root/libctf
diff options
context:
space:
mode:
Diffstat (limited to 'libctf')
-rw-r--r--libctf/ChangeLog23
-rw-r--r--libctf/ctf-decl.c5
-rw-r--r--libctf/ctf-dump.c308
-rw-r--r--libctf/ctf-types.c4
4 files changed, 199 insertions, 141 deletions
diff --git a/libctf/ChangeLog b/libctf/ChangeLog
index b914254..8ba75f3 100644
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -1,5 +1,28 @@
2021-01-05 Nick Alcock <nick.alcock@oracle.com>
+ * ctf-decl.c (ctf_decl_push): Exclude slices from the decl stack.
+ * ctf-types.c (ctf_type_aname): No longer deal with slices here.
+ * ctf-dump.c (ctf_dump_membstate_t) <cdm_toplevel_indent>: Constify.
+ (CTF_FT_REFS): New.
+ (CTF_FT_BITFIELD): Likewise.
+ (CTF_FT_ID): Likewise.
+ (ctf_dump_member): Do not do indentation here. Migrate the
+ type-printing parts of this into...
+ (ctf_dump_format_type): ... here, to be shared by all type printers.
+ Get the errno value for non-representable types right. Do not print
+ bitfield info for non-bitfields. Improve the format and indentation
+ of other type output. Shuffle spacing around to make all indentation
+ either 'width of column' or 4 chars.
+ (ctf_dump_label): Pass CTF_FT_REFS to ctf_dump_format_type.
+ (ctf_dump_objts): Likewise. Spacing shuffle.
+ (ctf_dump_var): Likewise.
+ (type_hex_digits): Migrate down in the file, to above its new user.
+ (ctf_dump_type): Indent here instead. Pass CTF_FT_REFS to
+ ctf_dump_format_type. Don't trim off excess linefeeds now we no
+ longer generate them. Dump enumerated types.
+
+2021-01-05 Nick Alcock <nick.alcock@oracle.com>
+
* ctf-types.c (ctf_type_resolve): Improve comment.
(ctf_type_size): Yield ECTF_INCOMPLETE when applied to forwards.
Emit errors into the right dict.
diff --git a/libctf/ctf-decl.c b/libctf/ctf-decl.c
index 232ff5d..269eca4 100644
--- a/libctf/ctf-decl.c
+++ b/libctf/ctf-decl.c
@@ -117,9 +117,10 @@ ctf_decl_push (ctf_decl_t *cd, ctf_dict_t *fp, ctf_id_t type)
break;
case CTF_K_SLICE:
+ /* Slices themselves have no print representation and should not appear in
+ the decl stack. */
ctf_decl_push (cd, fp, ctf_type_reference (fp, type));
- prec = CTF_PREC_BASE;
- break;
+ return;
case CTF_K_VOLATILE:
case CTF_K_CONST:
diff --git a/libctf/ctf-dump.c b/libctf/ctf-dump.c
index abed483..758d28d 100644
--- a/libctf/ctf-dump.c
+++ b/libctf/ctf-dump.c
@@ -47,7 +47,7 @@ typedef struct ctf_dump_membstate
{
char **cdm_str;
ctf_dict_t *cdm_fp;
- char *cdm_toplevel_indent;
+ const char *cdm_toplevel_indent;
} ctf_dump_membstate_t;
static int
@@ -80,8 +80,12 @@ ctf_dump_free (ctf_dump_state_t *state)
}
}
-/* Return a dump for a single type, without member info: but do show the
- type's references. */
+/* Return a dump for a single type, without member info: but do optionally show
+ the type's references. */
+
+#define CTF_FT_REFS 0x2 /* Print referenced types. */
+#define CTF_FT_BITFIELD 0x4 /* Print :BITS if a bitfield. */
+#define CTF_FT_ID 0x8 /* Print "ID: " in front of type IDs. */
static char *
ctf_dump_format_type (ctf_dict_t *fp, ctf_id_t id, int flag)
@@ -89,14 +93,16 @@ ctf_dump_format_type (ctf_dict_t *fp, ctf_id_t id, int flag)
ctf_id_t new_id;
char *str = NULL, *bit = NULL, *buf = NULL;
+ ctf_set_errno (fp, 0);
new_id = id;
do
{
- ctf_encoding_t enc;
+ ctf_encoding_t ep;
ctf_arinfo_t ar;
int kind, unsliced_kind;
const char *nonroot_leader = "";
const char *nonroot_trailer = "";
+ const char *idstr = "";
id = new_id;
if (flag == CTF_ADD_NONROOT)
@@ -110,15 +116,18 @@ ctf_dump_format_type (ctf_dict_t *fp, ctf_id_t id, int flag)
{
if (id == 0 || ctf_errno (fp) == ECTF_NONREPRESENTABLE)
{
+ ctf_set_errno (fp, ECTF_NONREPRESENTABLE);
str = str_append (str, " (type not represented in CTF)");
- ctf_set_errno (fp, ECTF_NOTREF);
- break;
+ return str;
}
goto err;
}
- if (asprintf (&bit, " %s0x%lx: ", nonroot_leader, id) < 0)
+ if (flag & CTF_FT_ID)
+ idstr = "ID ";
+ if (asprintf (&bit, "%s%s0x%lx: (kind %i) ", nonroot_leader, idstr,
+ id, ctf_type_kind (fp, id)) < 0)
goto oom;
str = str_append (str, bit);
free (bit);
@@ -129,37 +138,74 @@ ctf_dump_format_type (ctf_dict_t *fp, ctf_id_t id, int flag)
free (buf);
buf = NULL;
+
unsliced_kind = ctf_type_kind_unsliced (fp, id);
kind = ctf_type_kind (fp, id);
- /* Slices get a different print representation. */
- if (unsliced_kind == CTF_K_SLICE)
+ if (ctf_type_encoding (fp, id, &ep) == 0)
{
- ctf_type_encoding (fp, id, &enc);
- if (asprintf (&bit, " [slice 0x%x:0x%x]",
- enc.cte_offset, enc.cte_bits) < 0)
+ if (ep.cte_bits != ctf_type_size (fp, id) * CHAR_BIT
+ && flag & CTF_FT_BITFIELD)
+ {
+ if (asprintf (&bit, ":%i", ep.cte_bits) < 0)
+ goto oom;
+ str = str_append (str, bit);
+ free (bit);
+ bit = NULL;
+ }
+
+ if (ep.cte_bits != ctf_type_size (fp, id) * CHAR_BIT
+ || ep.cte_offset != 0)
+ {
+ const char *slice = "";
+
+ if (unsliced_kind == CTF_K_SLICE)
+ slice = "slice ";
+
+ if (asprintf (&bit, " [%s0x%x:0x%x]",
+ slice, ep.cte_offset, ep.cte_bits) < 0)
+ goto oom;
+ str = str_append (str, bit);
+ free (bit);
+ bit = NULL;
+ }
+
+ if (asprintf (&bit, " (format 0x%x)", ep.cte_format) < 0)
goto oom;
+ str = str_append (str, bit);
+ free (bit);
+ bit = NULL;
}
- else if (kind == CTF_K_INTEGER)
+
+ if (kind != CTF_K_FUNCTION && kind != CTF_K_FORWARD)
{
- ctf_type_encoding (fp, id, &enc);
- if (asprintf (&bit, " [0x%x:0x%x]",
- enc.cte_offset, enc.cte_bits) < 0)
+ if (asprintf (&bit, " (size 0x%lx)",
+ (unsigned long) ctf_type_size (fp, id)) < 0)
goto oom;
+
+ str = str_append (str, bit);
+ free (bit);
+ bit = NULL;
}
- str = str_append (str, bit);
- free (bit);
- bit = NULL;
- if (kind != CTF_K_FUNCTION && kind != CTF_K_FORWARD)
- if (asprintf (&bit, " (size 0x%lx)%s",
- (unsigned long) ctf_type_size (fp, id),
- nonroot_trailer) < 0)
- goto oom;
+ if (kind != CTF_K_FORWARD)
+ {
+ if (asprintf (&bit, " (aligned at 0x%lx)",
+ (unsigned long) ctf_type_align (fp, id)) < 0)
+ goto oom;
- str = str_append (str, bit);
- free (bit);
- bit = NULL;
+ str = str_append (str, bit);
+ free (bit);
+ bit = NULL;
+ }
+
+ if (nonroot_trailer[0] != 0)
+ str = str_append (str, nonroot_trailer);
+
+ /* Just exit after one iteration if we are not showing the types this type
+ references. */
+ if (!(flag & CTF_FT_REFS))
+ return str;
/* Keep going as long as this type references another. We consider arrays
to "reference" their element type. */
@@ -173,7 +219,7 @@ ctf_dump_format_type (ctf_dict_t *fp, ctf_id_t id, int flag)
else
new_id = ctf_type_reference (fp, id);
if (new_id != CTF_ERR)
- str = str_append (str, " ->");
+ str = str_append (str, " -> ");
} while (new_id != CTF_ERR);
if (ctf_errno (fp) != ECTF_NOTREF)
@@ -363,7 +409,7 @@ ctf_dump_label (const char *name, const ctf_lblinfo_t *info,
return (ctf_set_errno (state->cds_fp, errno));
if ((typestr = ctf_dump_format_type (state->cds_fp, info->ctb_type,
- CTF_ADD_ROOT)) == NULL)
+ CTF_ADD_ROOT | CTF_FT_REFS)) == NULL)
{
free (str);
return 0; /* Swallow the error. */
@@ -400,14 +446,14 @@ ctf_dump_objts (ctf_dict_t *fp, ctf_dump_state_t *state, int functions)
has a leading one. */
if (name)
{
- if (asprintf (&str, "%s ->", name) < 0)
+ if (asprintf (&str, "%s -> ", name) < 0)
goto oom;
}
else
str = xstrdup ("");
if ((typestr = ctf_dump_format_type (state->cds_fp, id,
- CTF_ADD_ROOT)) == NULL)
+ CTF_ADD_ROOT | CTF_FT_REFS)) == NULL)
{
ctf_dump_append (state, str);
continue; /* Swallow the error. */
@@ -438,7 +484,7 @@ ctf_dump_var (const char *name, ctf_id_t type, void *arg)
return (ctf_set_errno (state->cds_fp, errno));
if ((typestr = ctf_dump_format_type (state->cds_fp, type,
- CTF_ADD_ROOT)) == NULL)
+ CTF_ADD_ROOT | CTF_FT_REFS)) == NULL)
{
free (str);
return 0; /* Swallow the error. */
@@ -451,22 +497,7 @@ ctf_dump_var (const char *name, ctf_id_t type, void *arg)
return 0;
}
-/* Report the number of digits in the hexadecimal representation of a type
- ID. */
-
-static int
-type_hex_digits (ctf_id_t id)
-{
- int i = 0;
-
- if (id == 0)
- return 1;
-
- for (; id > 0; id >>= 4, i++);
- return i;
-}
-
-/* Dump a single member into the string in the membstate. */
+/* Dump a single struct/union member into the string in the membstate. */
static int
ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset,
int depth, void *arg)
@@ -474,72 +505,23 @@ ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset,
ctf_dump_membstate_t *state = arg;
char *typestr = NULL;
char *bit = NULL;
- ctf_encoding_t ep;
- int has_encoding = 0;
- int opened_paren = 0;
-
- /* Align neatly. */
+ /* The struct/union itself has already been printed. */
if (depth == 0)
- {
- if (asprintf (&state->cdm_toplevel_indent, " %*s",
- type_hex_digits (id), "") < 0)
- goto oom;
- }
+ return 0;
- if (asprintf (&bit, "%s%*s", state->cdm_toplevel_indent, depth * 4, "") < 0)
+ if (asprintf (&bit, "%s%*s", state->cdm_toplevel_indent, (depth-1)*4, "") < 0)
goto oom;
*state->cdm_str = str_append (*state->cdm_str, bit);
free (bit);
- if ((typestr = ctf_type_aname (state->cdm_fp, id)) == NULL)
- {
- if (id == 0 || ctf_errno (state->cdm_fp) == ECTF_NONREPRESENTABLE)
- {
- if (asprintf (&bit, "[0x%lx] (type not represented in CTF)",
- offset) < 0)
- goto oom;
-
- *state->cdm_str = str_append (*state->cdm_str, bit);
- free (typestr);
- free (bit);
- return 0;
- }
+ if ((typestr = ctf_dump_format_type (state->cdm_fp, id,
+ CTF_ADD_ROOT | CTF_FT_BITFIELD
+ | CTF_FT_ID)) == NULL)
+ return -1; /* errno is set for us. */
- return -1; /* errno is set for us. */
- }
-
- if (ctf_type_encoding (state->cdm_fp, id, &ep) == 0)
- {
- has_encoding = 1;
- ctf_type_encoding (state->cdm_fp, id, &ep);
-
- if (asprintf (&bit, "[0x%lx] (ID 0x%lx) (kind %i) %s%s%s:%i "
- "(aligned at 0x%lx", offset, id,
- ctf_type_kind (state->cdm_fp, id), typestr,
- (name[0] != 0 && typestr[0] != 0) ? " " : "", name,
- ep.cte_bits, (unsigned long) ctf_type_align (state->cdm_fp,
- id)) < 0)
- goto oom;
- opened_paren = 1;
- }
- else if (ctf_type_kind (state->cdm_fp, id) != CTF_K_FORWARD)
- {
- if (asprintf (&bit, "[0x%lx] (ID 0x%lx) (kind %i) %s%s%s "
- "(aligned at 0x%lx", offset, id,
- ctf_type_kind (state->cdm_fp, id), typestr,
- (name[0] != 0 && typestr[0] != 0) ? " " : "", name,
- (unsigned long) ctf_type_align (state->cdm_fp, id)) < 0)
- goto oom;
- opened_paren = 1;
- }
- else /* Forwards have no alignment. */
- {
- if (asprintf (&bit, "[0x%lx] (ID 0x%lx) (kind %i) %s%s%s\n", offset, id,
- ctf_type_kind (state->cdm_fp, id), typestr,
- (name[0] != 0 && typestr[0] != 0) ? " " : "", name) < 0)
- goto oom;
- }
+ if (asprintf (&bit, "[0x%lx] %s: %s\n", offset, name, typestr) < 0)
+ goto oom;
*state->cdm_str = str_append (*state->cdm_str, bit);
free (typestr);
@@ -547,18 +529,6 @@ ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset,
typestr = NULL;
bit = NULL;
- if (has_encoding)
- {
- if (asprintf (&bit, ", format 0x%x, offset:bits 0x%x:0x%x", ep.cte_format,
- ep.cte_offset, ep.cte_bits) < 0)
- goto oom;
- *state->cdm_str = str_append (*state->cdm_str, bit);
- free (bit);
- bit = NULL;
- }
-
- if (opened_paren)
- *state->cdm_str = str_append (*state->cdm_str, ")\n");
return 0;
oom:
@@ -567,44 +537,112 @@ ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset,
return (ctf_set_errno (state->cdm_fp, errno));
}
+/* Report the number of digits in the hexadecimal representation of a type
+ ID. */
+
+static int
+type_hex_digits (ctf_id_t id)
+{
+ int i = 0;
+
+ if (id == 0)
+ return 1;
+
+ for (; id > 0; id >>= 4, i++);
+ return i;
+}
+
/* Dump a single type into the cds_items. */
static int
ctf_dump_type (ctf_id_t id, int flag, void *arg)
{
char *str;
+ char *indent;
+ int err = 0;
ctf_dump_state_t *state = arg;
ctf_dump_membstate_t membstate = { &str, state->cds_fp, NULL };
- size_t len;
- if ((str = ctf_dump_format_type (state->cds_fp, id, flag)) == NULL)
- goto err;
+ /* Indent neatly. */
+ if (asprintf (&indent, " %*s", type_hex_digits (id), "") < 0)
+ return (ctf_set_errno (state->cds_fp, ENOMEM));
+ /* Dump the type itself. */
+ if ((str = ctf_dump_format_type (state->cds_fp, id,
+ flag | CTF_FT_REFS)) == NULL)
+ goto err;
str = str_append (str, "\n");
- if ((ctf_type_visit (state->cds_fp, id, ctf_dump_member, &membstate)) < 0)
+
+ membstate.cdm_toplevel_indent = indent;
+
+ /* Member dumping for structs, unions... */
+ if (ctf_type_kind (state->cds_fp, id) == CTF_K_STRUCT
+ || ctf_type_kind (state->cds_fp, id) == CTF_K_UNION)
{
- if (id == 0 || ctf_errno (state->cds_fp) == ECTF_NONREPRESENTABLE)
+ if ((ctf_type_visit (state->cds_fp, id, ctf_dump_member, &membstate)) < 0)
{
- ctf_dump_append (state, str);
- return 0;
+ if (id == 0 || ctf_errno (state->cds_fp) == ECTF_NONREPRESENTABLE)
+ {
+ ctf_dump_append (state, str);
+ return 0;
+ }
+ ctf_err_warn (state->cds_fp, 1, ctf_errno (state->cds_fp),
+ _("cannot visit members dumping type 0x%lx"), id);
+ goto err;
}
- ctf_err_warn (state->cds_fp, 1, ctf_errno (state->cds_fp),
- _("cannot visit members dumping type 0x%lx"), id);
- goto err;
}
- free (membstate.cdm_toplevel_indent);
- /* Trim off the last linefeed added by ctf_dump_member(). */
- len = strlen (str);
- if (str[len-1] == '\n')
- str[len-1] = '\0';
+ /* ... and enums, for which we dump the first and last few members and skip
+ the ones in the middle. */
+ if (ctf_type_kind (state->cds_fp, id) == CTF_K_ENUM)
+ {
+ int enum_count = ctf_member_count (state->cds_fp, id);
+ ctf_next_t *it = NULL;
+ int i = 0;
+ const char *enumerand;
+ char *bit;
+ int value;
+
+ while ((enumerand = ctf_enum_next (state->cds_fp, id,
+ &it, &value)) != NULL)
+ {
+ i++;
+ if ((i > 5) && (i < enum_count - 4))
+ continue;
+
+ str = str_append (str, indent);
+
+ if (asprintf (&bit, "%s: %i\n", enumerand, value) < 0)
+ {
+ err = ENOMEM;
+ ctf_next_destroy (it);
+ goto err;
+ }
+ str = str_append (str, bit);
+ free (bit);
+
+ if ((i == 5) && (enum_count > 10))
+ {
+ str = str_append (str, indent);
+ str = str_append (str, "...\n");
+ }
+ }
+ if (ctf_errno (state->cds_fp) != ECTF_NEXT_END)
+ {
+ ctf_err_warn (state->cds_fp, 1, ctf_errno (state->cds_fp),
+ _("cannot visit enumerands dumping type 0x%lx"), id);
+ goto err;
+ }
+ }
ctf_dump_append (state, str);
+ free (indent);
+
return 0;
err:
- free (membstate.cdm_toplevel_indent);
+ free (indent);
free (str);
- return 0; /* Swallow the error. */
+ return ctf_set_errno (state->cds_fp, err);
}
/* Dump the string table into the cds_items. */
diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
index 3ba635f..a3d824b 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -826,10 +826,6 @@ ctf_type_aname (ctf_dict_t *fp, ctf_id_t type)
case CTF_K_RESTRICT:
ctf_decl_sprintf (&cd, "restrict");
break;
- case CTF_K_SLICE:
- /* No representation: just changes encoding of contained type,
- which is not in any case printed. Skip it. */
- break;
}
k = cdp->cd_kind;