From: Douglas Raillard <douglas.raillard@xxxxxxx> Use (struct tag).visited member to track what type has been printed already to avoid printing it twice. This allows producing a valid C header along with --expand_types. Signed-off-by: Douglas Raillard <douglas.raillard@xxxxxxx> --- dwarves.h | 3 ++- dwarves_fprintf.c | 22 ++++++++++++++++------ pahole.c | 34 ++++++++++++++++++---------------- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/dwarves.h b/dwarves.h index 52d162d..fc5b3fa 100644 --- a/dwarves.h +++ b/dwarves.h @@ -413,6 +413,7 @@ struct tag { type_id_t type; uint16_t tag; bool visited; + bool printed; bool top_level; bool has_btf_type_tag; uint16_t recursivity_level; @@ -1370,7 +1371,7 @@ static inline const char *enumerator__name(const struct enumerator *enumerator) void enumeration__delete(struct type *type); void enumeration__add(struct type *type, struct enumerator *enumerator); -size_t enumeration__fprintf(const struct tag *tag_enum, +size_t enumeration__fprintf(struct tag *tag_enum, const struct conf_fprintf *conf, FILE *fp); int dwarves__init(void); diff --git a/dwarves_fprintf.c b/dwarves_fprintf.c index c5921d7..2c5dce6 100644 --- a/dwarves_fprintf.c +++ b/dwarves_fprintf.c @@ -278,8 +278,8 @@ size_t typedef__fprintf(const struct tag *tag, const struct cu *cu, { struct type *type = tag__type(tag); const struct conf_fprintf *pconf = conf ?: &conf_fprintf__defaults; - const struct tag *tag_type; - const struct tag *ptr_type; + struct tag *tag_type; + struct tag *ptr_type; char bf[512]; int is_pointer = 0; size_t printed; @@ -394,13 +394,14 @@ out: return type->max_tag_name_len; } -size_t enumeration__fprintf(const struct tag *tag, const struct conf_fprintf *conf, FILE *fp) +size_t enumeration__fprintf(struct tag *tag, const struct conf_fprintf *conf, FILE *fp) { struct type *type = tag__type(tag); struct enumerator *pos; int max_entry_name_len = enumeration__max_entry_name_len(type); size_t printed = fprintf(fp, "enum%s%s {\n", type__name(type) ? " " : "", type__name(type) ?: ""); int indent = conf->indent; + tag->printed = 1; if (indent >= (int)sizeof(tabs)) indent = sizeof(tabs) - 1; @@ -651,10 +652,14 @@ static size_t type__fprintf(struct tag *type, const struct cu *cu, size_t printed = 0; int expand_types = conf->expand_types; int suppress_offset_comment = conf->suppress_offset_comment; + bool type_printed; if (type == NULL) goto out_type_not_found; + type_printed = type->printed; + type->printed = 1; + if (conf->expand_pointers) { int nr_indirections = 0; @@ -794,7 +799,7 @@ print_default: case DW_TAG_structure_type: ctype = tag__type(type); - if (type__name(ctype) != NULL && !expand_types) { + if (type__name(ctype) != NULL && (!expand_types || type_printed)) { printed += fprintf(fp, "%s %-*s %s", (type->tag == DW_TAG_class_type && !tconf.classes_as_structs) ? "class" : "struct", @@ -813,7 +818,7 @@ print_default: case DW_TAG_union_type: ctype = tag__type(type); - if (type__name(ctype) != NULL && !expand_types) { + if (type__name(ctype) != NULL && (!expand_types || type_printed)) { printed += fprintf(fp, "union %-*s %s", tconf.type_spacing - 6, type__name(ctype), name ?: ""); } else { tconf.type_spacing -= 8; @@ -823,7 +828,7 @@ print_default: case DW_TAG_enumeration_type: ctype = tag__type(type); - if (type__name(ctype) != NULL) + if (type__name(ctype) != NULL || type_printed) printed += fprintf(fp, "enum %-*s %s", tconf.type_spacing - 5, type__name(ctype), name ?: ""); else printed += enumeration__fprintf(type, &tconf, fp); @@ -1000,6 +1005,8 @@ static size_t union__fprintf(struct type *type, const struct cu *cu, uint32_t initial_union_cacheline; uint32_t cacheline = 0; /* This will only be used if this is the outermost union */ + type__tag(type)->printed = 1; + if (indent >= (int)sizeof(tabs)) indent = sizeof(tabs) - 1; @@ -1394,6 +1401,8 @@ static size_t __class__fprintf(struct class *class, const struct cu *cu, type__name(type) ?: ""); int indent = cconf.indent; + class__tag(class)->printed = 1; + if (indent >= (int)sizeof(tabs)) indent = sizeof(tabs) - 1; @@ -1856,6 +1865,7 @@ size_t tag__fprintf(struct tag *tag, const struct cu *cu, size_t printed = 0; struct conf_fprintf tconf; const struct conf_fprintf *pconf = conf; + tag->printed = 1; if (conf == NULL) { tconf = conf_fprintf__defaults; diff --git a/pahole.c b/pahole.c index f3a51cb..42ba110 100644 --- a/pahole.c +++ b/pahole.c @@ -2964,22 +2964,24 @@ out_btf: goto dump_it; } - if (class) - class__find_holes(tag__class(class)); - if (reorganize) { - if (class && tag__is_struct(class)) - do_reorg(class, cu); - } else if (find_containers) - print_containers(cu, class_id, 0); - else if (find_pointers_in_structs) - print_structs_with_pointer_to(cu, class_id); - else if (class) { - /* - * We don't need to print it for every compile unit - * but the previous options need - */ - tag__fprintf(class, cu, &conf, stdout); - putchar('\n'); + if (!class->printed) { + if (class) + class__find_holes(tag__class(class)); + if (reorganize) { + if (class && tag__is_struct(class)) + do_reorg(class, cu); + } else if (find_containers) + print_containers(cu, class_id, 0); + else if (find_pointers_in_structs) + print_structs_with_pointer_to(cu, class_id); + else if (class) { + /* + * We don't need to print it for every compile unit + * but the previous options need + */ + tag__fprintf(class, cu, &conf, stdout); + putchar('\n'); + } } } -- 2.25.1