diff options
Diffstat (limited to 'libctf')
-rw-r--r-- | libctf/ChangeLog | 23 | ||||
-rw-r--r-- | libctf/ctf-decl.c | 5 | ||||
-rw-r--r-- | libctf/ctf-dump.c | 308 | ||||
-rw-r--r-- | libctf/ctf-types.c | 4 |
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; |