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 <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2021-07-06 16:59:16 -03:00
parent 967290bc71
commit 3e1c7a2077
2 changed files with 44 additions and 1 deletions

View File

@ -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.

View File

@ -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