From 3e1c7a20770ec43206a46116db048f1759830217 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 6 Jul 2021 16:59:16 -0300 Subject: [PATCH] pahole: Introduce --sort To ask for sorting output, initially by name. This is needed in 'btfdiff' to diff the output of 'pahole -F dwarf --jobs N', where N threads will go on consuming DWARF compile units and and pretty printing them, producing a non deterministic output. So we need to sort the output for both BTF and DWARF, and then diff them. This is still not enough for some cases where different types have the same name, things like "usb_priv" that exists in multiple DWARF compile units, the first processed is "winning", i.e. being the only one considered. I have to look how BTF handles this to adopt a similar algorithm and keep btfdiff usable as a regression test for the BTF and DWARF loader and the BTF encoder. Signed-off-by: Arnaldo Carvalho de Melo --- man-pages/pahole.1 | 8 ++++++++ pahole.c | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/man-pages/pahole.1 b/man-pages/pahole.1 index a2bb920..4e79d56 100644 --- a/man-pages/pahole.1 +++ b/man-pages/pahole.1 @@ -100,6 +100,14 @@ or file URLs (e.g.: file://class_list.txt) .B \-c, \-\-cacheline_size=SIZE Set cacheline size to SIZE bytes. +.TP \-\-sort +Sort the output by type name, maybe this will grow to allow sorting by other +criteria. + +This is mostly needed so that pretty printing from BTF and DWARF can be +comparable when using using multiple threads to load DWARF data, when the order +that the types in the compile units is processed is not deterministic. + .TP .B \-\-count=COUNT Pretty print the first COUNT records from input. diff --git a/pahole.c b/pahole.c index ff761df..838e833 100644 --- a/pahole.c +++ b/pahole.c @@ -31,6 +31,7 @@ static char *detached_btf_filename; static bool btf_encode; static bool btf_gen_floats; static bool ctf_encode; +static bool sort_output; static bool first_obj_only; static bool skip_encoding_btf_vars; static bool btf_encode_force; @@ -354,11 +355,27 @@ static void print_classes(struct cu *cu) if (show_packable && !global_verbose) print_packable_info(pos, cu, id); + else if (sort_output && formatter == class_formatter) + continue; // we'll print it at the end, in order, out of structures__tree else if (formatter != NULL) formatter(pos, cu, id); } } +static void print_ordered_classes(void) +{ + struct rb_node *next = rb_first(&structures__tree); + + while (next) { + struct structure *st = rb_entry(next, struct structure, rb_node); + + class_formatter(st->class, st->cu, st->id); + + next = rb_next(&st->rb_node); + } + +} + static struct cu *cu__filter(struct cu *cu) { if (cu__exclude_prefix != NULL && @@ -882,6 +899,7 @@ ARGP_PROGRAM_VERSION_HOOK_DEF = dwarves_print_version; #define ARGP_kabi_prefix 325 #define ARGP_btf_encode_detached 326 #define ARGP_prettify_input_filename 327 +#define ARGP_sort_output 328 static const struct argp_option pahole__options[] = { { @@ -1230,6 +1248,11 @@ static const struct argp_option pahole__options[] = { .key = ARGP_numeric_version, .doc = "Print a numeric version, i.e. 119 instead of v1.19" }, + { + .name = "sort", + .key = ARGP_sort_output, + .doc = "Sort types by name", + }, { .name = "prettify", .key = ARGP_prettify_input_filename, @@ -1368,6 +1391,8 @@ static error_t pahole__options_parser(int key, char *arg, show_with_flexible_array = true; break; case ARGP_prettify_input_filename: prettify_input_filename = arg; break; + case ARGP_sort_output: + sort_output = true; break; default: return ARGP_ERR_UNKNOWN; } @@ -2551,6 +2576,10 @@ static enum load_steal_kind pahole_stealer(struct cu *cu, cu_fixup_word_size_iterator(cu); print_classes(cu); + + if (sort_output && formatter == class_formatter) + ret = LSK__KEEPIT; + goto dump_it; } @@ -2918,6 +2947,11 @@ try_sole_arg_as_class_names: goto out_cus_delete; } + if (sort_output && formatter == class_formatter) { + print_ordered_classes(); + goto out_ok; + } + if (!list_empty(&class_names)) { struct prototype *prototype; @@ -2962,9 +2996,10 @@ try_sole_arg_as_class_names: goto out_cus_delete; } } - +out_ok: if (stats_formatter != NULL) print_stats(); + rc = EXIT_SUCCESS; out_cus_delete: #ifdef DEBUG_CHECK_LEAKS