X-Git-Url: https://repo.jachan.dev/binutils.git/blobdiff_plain/b4f0e09cd18e0dbeeecd303ed54f6f113146e857..a0cc569d599f92c3a9168fcd23a0b18f7ff42f1d:/libctf/ctf-dump.c diff --git a/libctf/ctf-dump.c b/libctf/ctf-dump.c index 0c0c2246b5..b6af0dfe41 100644 --- a/libctf/ctf-dump.c +++ b/libctf/ctf-dump.c @@ -1,5 +1,5 @@ /* Textual dumping of CTF data. - Copyright (C) 2019 Free Software Foundation, Inc. + Copyright (C) 2019-2021 Free Software Foundation, Inc. This file is part of libctf. @@ -20,6 +20,8 @@ #include #include +#define str_append(s, a) ctf_str_append_noerr (s, a) + /* One item to be dumped, in string form. */ typedef struct ctf_dump_item @@ -34,7 +36,7 @@ typedef struct ctf_dump_item struct ctf_dump_state { ctf_sect_names_t cds_sect; - ctf_file_t *cds_fp; + ctf_dict_t *cds_fp; ctf_dump_item_t *cds_current; ctf_list_t cds_items; }; @@ -44,7 +46,8 @@ struct ctf_dump_state typedef struct ctf_dump_membstate { char **cdm_str; - ctf_file_t *cdm_fp; + ctf_dict_t *cdm_fp; + const char *cdm_toplevel_indent; } ctf_dump_membstate_t; static int @@ -52,7 +55,7 @@ ctf_dump_append (ctf_dump_state_t *state, char *str) { ctf_dump_item_t *cdi; - if ((cdi = ctf_alloc (sizeof (struct ctf_dump_item))) == NULL) + if ((cdi = malloc (sizeof (struct ctf_dump_item))) == NULL) return (ctf_set_errno (state->cds_fp, ENOMEM)); cdi->cdi_item = str; @@ -73,39 +76,34 @@ ctf_dump_free (ctf_dump_state_t *state) { free (cdi->cdi_item); next_cdi = ctf_list_next (cdi); - ctf_free (cdi); + free (cdi); } } -/* Slices need special handling to distinguish them from their referenced - type. */ - -static int -ctf_is_slice (ctf_file_t *fp, ctf_id_t id, ctf_encoding_t *enc) -{ - int kind = ctf_type_kind (fp, id); - - return (((kind == CTF_K_INTEGER) || (kind == CTF_K_ENUM) - || (kind == CTF_K_FLOAT)) - && ctf_type_reference (fp, id) != CTF_ERR - && ctf_type_encoding (fp, id, enc) == 0); -} +/* Return a dump for a single type, without member info: but do optionally show + the type's references. */ -/* Return a dump for a single type, without member info: but do 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_file_t *fp, ctf_id_t id, int flag) +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; + ssize_t size, align; const char *nonroot_leader = ""; const char *nonroot_trailer = ""; + const char *idstr = ""; id = new_id; if (flag == CTF_ADD_NONROOT) @@ -116,36 +114,119 @@ ctf_dump_format_type (ctf_file_t *fp, ctf_id_t id, int flag) buf = ctf_type_aname (fp, id); if (!buf) + { + if (id == 0 || ctf_errno (fp) == ECTF_NONREPRESENTABLE) + { + ctf_set_errno (fp, ECTF_NONREPRESENTABLE); + str = str_append (str, " (type not represented in CTF)"); + return str; + } + + goto err; + } + + 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); + bit = NULL; - /* Slices get a different print representation. */ + if (buf[0] != '\0') + str = str_append (str, buf); - if (ctf_is_slice (fp, id, &enc)) + free (buf); + buf = NULL; + + unsliced_kind = ctf_type_kind_unsliced (fp, id); + kind = ctf_type_kind (fp, id); + + /* Report encodings of everything with an encoding other than enums: + base-type enums cannot have a nonzero cte_offset or cte_bits value. + (Slices of them can, but they are of kind CTF_K_SLICE.) */ + if (unsliced_kind != CTF_K_ENUM && ctf_type_encoding (fp, id, &ep) == 0) { - ctf_type_encoding (fp, id, &enc); - if (asprintf (&bit, " %s%lx: [slice 0x%x:0x%x]%s", - nonroot_leader, id, enc.cte_offset, enc.cte_bits, - nonroot_trailer) < 0) + if ((ssize_t) 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 ((ssize_t) 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 + + size = ctf_type_size (fp, id); + if (kind != CTF_K_FUNCTION && size >= 0) { - if (asprintf (&bit, " %s%lx: %s (size 0x%lx)%s", nonroot_leader, - id, buf[0] == '\0' ? "(nameless)" : buf, - (unsigned long) ctf_type_size (fp, id), - nonroot_trailer) < 0) + if (asprintf (&bit, " (size 0x%lx)", (unsigned long int) size) < 0) goto oom; + + str = str_append (str, bit); + free (bit); + bit = NULL; } - free (buf); - buf = NULL; - str = ctf_str_append (str, bit); - free (bit); - bit = NULL; - new_id = ctf_type_reference (fp, id); + align = ctf_type_align (fp, id); + if (align >= 0) + { + if (asprintf (&bit, " (aligned at 0x%lx)", + (unsigned long int) align) < 0) + goto oom; + + 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. */ + + if (kind == CTF_K_ARRAY) + { + if (ctf_array_info (fp, id, &ar) < 0) + goto err; + new_id = ar.ctr_contents; + } + else + new_id = ctf_type_reference (fp, id); if (new_id != CTF_ERR) - str = ctf_str_append (str, " ->"); - } while (new_id != CTF_ERR); + str = str_append (str, " -> "); + } + while (new_id != CTF_ERR); if (ctf_errno (fp) != ECTF_NOTREF) { @@ -156,16 +237,18 @@ ctf_dump_format_type (ctf_file_t *fp, ctf_id_t id, int flag) return str; oom: + ctf_set_errno (fp, errno); + err: + ctf_err_warn (fp, 1, 0, _("cannot format name dumping type 0x%lx"), id); free (buf); free (str); free (bit); - ctf_set_errno (fp, ENOMEM); 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, +ctf_dump_header_strfield (ctf_dict_t *fp, ctf_dump_state_t *state, const char *name, uint32_t value) { char *str; @@ -178,12 +261,12 @@ ctf_dump_header_strfield (ctf_file_t *fp, ctf_dump_state_t *state, return 0; err: - return (ctf_set_errno (fp, -ENOMEM)); + return (ctf_set_errno (fp, errno)); } /* 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, +ctf_dump_header_sectfield (ctf_dict_t *fp, ctf_dump_state_t *state, const char *sect, uint32_t off, uint32_t nextoff) { char *str; @@ -198,14 +281,15 @@ ctf_dump_header_sectfield (ctf_file_t *fp, ctf_dump_state_t *state, return 0; err: - return (ctf_set_errno (fp, -ENOMEM)); + return (ctf_set_errno (fp, errno)); } /* Dump the file header into the cds_items. */ static int -ctf_dump_header (ctf_file_t *fp, ctf_dump_state_t *state) +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[] = { @@ -217,7 +301,7 @@ ctf_dump_header (ctf_file_t *fp, ctf_dump_state_t *state) }; const char *verstr = NULL; - if (asprintf (&str, "Magic number: %x\n", hp->cth_magic) < 0) + if (asprintf (&str, "Magic number: 0x%x\n", hp->cth_magic) < 0) goto err; ctf_dump_append (state, str); @@ -234,17 +318,36 @@ ctf_dump_header (ctf_file_t *fp, ctf_dump_state_t *state) /* Everything else is only printed if present. */ - /* The flags are unusual in that they represent the ctf_file_t *in memory*: + /* The flags are unusual in that they represent the ctf_dict_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) + 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); } @@ -269,7 +372,15 @@ ctf_dump_header (ctf_file_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", @@ -286,7 +397,8 @@ ctf_dump_header (ctf_file_t *fp, ctf_dump_state_t *state) return 0; err: - return (ctf_set_errno (fp, -ENOMEM)); + free (flagstr); + return (ctf_set_errno (fp, errno)); } /* Dump a single label into the cds_items. */ @@ -300,167 +412,68 @@ ctf_dump_label (const char *name, const ctf_lblinfo_t *info, ctf_dump_state_t *state = arg; if (asprintf (&str, "%s -> ", name) < 0) - return (ctf_set_errno (state->cds_fp, ENOMEM)); + 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 -1; /* errno is set for us. */ + return 0; /* Swallow the error. */ } - str = ctf_str_append (str, typestr); + str = str_append (str, typestr); free (typestr); ctf_dump_append (state, str); 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. */ - -static int -ctf_dump_objts (ctf_file_t *fp, ctf_dump_state_t *state) -{ - size_t i; - - for (i = 0; i < fp->ctf_nsyms; i++) - { - char *str; - char *typestr; - const char *sym_name; - ctf_id_t type; - - 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') - { - if (asprintf (&str, "%lx -> ", (unsigned long) i) < 0) - return (ctf_set_errno (fp, ENOMEM)); - } - else - { - if (asprintf (&str, "%s (%lx) -> ", sym_name, (unsigned long) i) < 0) - return (ctf_set_errno (fp, ENOMEM)); - } - - /* Variable type. */ - if ((typestr = ctf_dump_format_type (state->cds_fp, type, - CTF_ADD_ROOT)) == NULL) - { - free (str); - return -1; /* errno is set for us. */ - } - - str = ctf_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.) */ +/* Dump all the object or function entries into the cds_items. */ static int -ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state) +ctf_dump_objts (ctf_dict_t *fp, ctf_dump_state_t *state, int functions) { - size_t i; - - for (i = 0; i < fp->ctf_nsyms; i++) + const char *name; + ctf_id_t id; + ctf_next_t *i = NULL; + char *str = NULL; + + 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 *bit; - const char *sym_name; - ctf_funcinfo_t fi; - ctf_id_t type; - size_t j; - ctf_id_t *args; - - 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_NOTYPEDAT: - continue; - } - if ((args = calloc (fi.ctc_argc, sizeof (ctf_id_t))) == NULL) - return (ctf_set_errno (fp, ENOMEM)); - - /* Return type. */ - if ((str = ctf_type_aname (state->cds_fp, type)) == NULL) - goto err; - - str = ctf_str_append (str, " "); - - /* Function name. */ + char *typestr = NULL; - sym_name = ctf_lookup_symbol_name (fp, i); - if (sym_name[0] == '\0') + /* Emit the name, if we know it. No trailing space: ctf_dump_format_type + has a leading one. */ + if (name) { - if (asprintf (&bit, "0x%lx ", (unsigned long) i) < 0) + if (asprintf (&str, "%s -> ", name) < 0) goto oom; } else - { - if (asprintf (&bit, "%s (0x%lx) ", sym_name, (unsigned long) i) < 0) - goto oom; - } - str = ctf_str_append (str, bit); - str = ctf_str_append (str, " ("); - free (bit); - - /* Function arguments. */ + str = xstrdup (""); - if (ctf_func_args (state->cds_fp, i, fi.ctc_argc, args) < 0) - goto err; - - for (j = 0; j < fi.ctc_argc; j++) + if ((typestr = ctf_dump_format_type (state->cds_fp, id, + CTF_ADD_ROOT | CTF_FT_REFS)) == NULL) { - if ((bit = ctf_type_aname (state->cds_fp, args[j])) == NULL) - goto err; - str = ctf_str_append (str, bit); - if ((j < fi.ctc_argc - 1) || (fi.ctc_flags & CTF_FUNC_VARARG)) - str = ctf_str_append (str, ", "); - free (bit); + ctf_dump_append (state, str); + continue; /* Swallow the error. */ } - if (fi.ctc_flags & CTF_FUNC_VARARG) - str = ctf_str_append (str, "..."); - str = ctf_str_append (str, ")"); - - free (args); + str = str_append (str, typestr); + free (typestr); ctf_dump_append (state, str); continue; oom: - free (args); - free (str); - return (ctf_set_errno (fp, ENOMEM)); - err: - free (args); - free (str); - return -1; /* errno is set for us. */ + ctf_set_errno (fp, ENOMEM); + ctf_next_destroy (i); + return -1; } return 0; } @@ -474,105 +487,180 @@ ctf_dump_var (const char *name, ctf_id_t type, void *arg) ctf_dump_state_t *state = arg; if (asprintf (&str, "%s -> ", name) < 0) - return (ctf_set_errno (state->cds_fp, ENOMEM)); + 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 -1; /* errno is set for us. */ + return 0; /* Swallow the error. */ } - str = ctf_str_append (str, typestr); + str = str_append (str, typestr); free (typestr); ctf_dump_append (state, str); return 0; } -/* 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) + int depth, void *arg) { ctf_dump_membstate_t *state = arg; char *typestr = NULL; char *bit = NULL; - ctf_encoding_t ep; - ssize_t i; - for (i = 0; i < depth; i++) - *state->cdm_str = ctf_str_append (*state->cdm_str, " "); + /* The struct/union itself has already been printed. */ + if (depth == 0) + return 0; - if ((typestr = ctf_type_aname (state->cdm_fp, id)) == NULL) + 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 (asprintf (&bit, " [0x%lx] (ID 0x%lx) (kind %i) %s %s (aligned at 0x%lx", - offset, id, ctf_type_kind (state->cdm_fp, id), typestr, name, - (unsigned long) ctf_type_align (state->cdm_fp, id)) < 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. */ + + if (asprintf (&bit, "[0x%lx] %s: %s\n", offset, name, typestr) < 0) goto oom; - *state->cdm_str = ctf_str_append (*state->cdm_str, bit); + + *state->cdm_str = str_append (*state->cdm_str, bit); free (typestr); free (bit); typestr = NULL; bit = NULL; - if ((ctf_type_kind (state->cdm_fp, id) == CTF_K_INTEGER) - || (ctf_type_kind (state->cdm_fp, id) == CTF_K_FLOAT) - || (ctf_is_slice (state->cdm_fp, id, &ep) == CTF_K_ENUM)) - { - ctf_type_encoding (state->cdm_fp, id, &ep); - 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 = ctf_str_append (*state->cdm_str, bit); - free (bit); - bit = NULL; - } - - *state->cdm_str = ctf_str_append (*state->cdm_str, ")\n"); return 0; oom: free (typestr); free (bit); - return (ctf_set_errno (state->cdm_fp, ENOMEM)); + return (ctf_set_errno (state->cdm_fp, errno)); } -/* Dump a single type into the cds_items. */ +/* 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; ctf_dump_state_t *state = arg; - ctf_dump_membstate_t membstate = { &str, state->cds_fp }; - size_t len; + ctf_dump_membstate_t membstate = { &str, state->cds_fp, NULL }; - 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)); - str = ctf_str_append (str, "\n"); - if ((ctf_type_visit (state->cds_fp, id, ctf_dump_member, &membstate)) < 0) + /* 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"); + + 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 ((ctf_type_visit (state->cds_fp, id, ctf_dump_member, &membstate)) < 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; + } + } + + /* ... 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; - /* Trim off the last linefeed added by ctf_dump_member(). */ - len = strlen (str); - if (str[len-1] == '\n') - str[len-1] = '\0'; + str = str_append (str, indent); + + if (asprintf (&bit, "%s: %i\n", enumerand, value) < 0) + { + ctf_next_destroy (it); + goto oom; + } + 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 (indent); free (str); - return -1; /* errno is set for us. */ + + /* Swallow the error: don't cause an error in one type to abort all + type dumping. */ + return 0; + + oom: + free (indent); + free (str); + return ctf_set_errno (state->cds_fp, ENOMEM); } /* Dump the string table into the cds_items. */ static int -ctf_dump_str (ctf_file_t *fp, ctf_dump_state_t *state) +ctf_dump_str (ctf_dict_t *fp, ctf_dump_state_t *state) { const char *s = fp->ctf_str[CTF_STRTAB_0].cts_strs; @@ -580,10 +668,10 @@ ctf_dump_str (ctf_file_t *fp, ctf_dump_state_t *state) fp->ctf_str[CTF_STRTAB_0].cts_len;) { char *str; - if (asprintf (&str, "%lx: %s", + if (asprintf (&str, "0x%lx: %s", (unsigned long) (s - fp->ctf_str[CTF_STRTAB_0].cts_strs), s) < 0) - return (ctf_set_errno (fp, ENOMEM)); + return (ctf_set_errno (fp, errno)); ctf_dump_append (state, str); s += strlen (s) + 1; } @@ -602,7 +690,7 @@ ctf_dump_str (ctf_file_t *fp, ctf_dump_state_t *state) allocate a new one and return it if it likes). */ char * -ctf_dump (ctf_file_t *fp, ctf_dump_state_t **statep, ctf_sect_names_t sect, +ctf_dump (ctf_dict_t *fp, ctf_dump_state_t **statep, ctf_sect_names_t sect, ctf_dump_decorate_f *func, void *arg) { char *str; @@ -617,7 +705,7 @@ ctf_dump (ctf_file_t *fp, ctf_dump_state_t **statep, ctf_sect_names_t sect, by bit. The first call will take (much) longer than otherwise, but the amortized time needed is the same. */ - if ((*statep = ctf_alloc (sizeof (struct ctf_dump_state))) == NULL) + if ((*statep = malloc (sizeof (struct ctf_dump_state))) == NULL) { ctf_set_errno (fp, ENOMEM); goto end; @@ -642,11 +730,11 @@ ctf_dump (ctf_file_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: @@ -701,8 +789,8 @@ ctf_dump (ctf_file_t *fp, ctf_dump_state_t **statep, ctf_sect_names_t sect, nline[0] = '\0'; ret = func (sect, line, arg); - str = ctf_str_append (str, ret); - str = ctf_str_append (str, "\n"); + str = str_append (str, ret); + str = str_append (str, "\n"); if (ret != line) free (ret); @@ -721,14 +809,21 @@ ctf_dump (ctf_file_t *fp, ctf_dump_state_t **statep, ctf_sect_names_t sect, str[len-1] = '\0'; } else - str = strdup (state->cds_current->cdi_item); + { + str = strdup (state->cds_current->cdi_item); + if (!str) + { + ctf_set_errno (fp, ENOMEM); + return str; + } + } ctf_set_errno (fp, 0); return str; end: ctf_dump_free (state); - ctf_free (state); + free (state); ctf_set_errno (fp, 0); *statep = NULL; return NULL;