Skip to content

Commit

Permalink
pahole: Introduce --lang to ask for only compilation units written in…
Browse files Browse the repository at this point in the history
… some languages

Works with all options, i.e. to test it one can use:

$ pahole --lang rust

And, using /sys/kernel/btf/vmlinux, the default, nothing will be
printed, as BTF doesn't have the language information and everything is
considered to be written in "C".

So, still using BTF, this:

$ pahole --lang c

is equivalent to:

$ pahole

I.e. will print all types.

Using DWARF it will use the DW_AT_language attribute of the
DW_TAG_compile_unit to honour this filter.

I.e.:

$ pahole -F dwarf --lang c,c89,rust

is equivalent to:

$ pahole -F dwarf

As the kernel is written in those languages.

The real use case will be serviced in the following patch, which is to
not process compilation units written in rust when generating BTF.

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
  • Loading branch information
acmel committed Apr 25, 2022
1 parent c3f2fe2 commit 8ee3637
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 0 deletions.
13 changes: 13 additions & 0 deletions man-pages/pahole.1
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,19 @@ Exclude PREFIXed classes.
.B \-X, \-\-cu_exclude=PREFIX
Exclude PREFIXed compilation units.

.TP
.B \-\-lang=languages
Only process compilation units built from source code written in the specified languages.

Supported languages:

ada83, ada95, bliss, c, c89, c99, c11, c++, c++03, c++11, c++14, cobol74,
cobol85, d, dylan, fortran77, fortran90, fortran95, fortran03, fortran08,
go, haskell, java, julia, modula2, modula3, objc, objc++, ocaml, opencl,
pascal83, pli, python, renderscript, rust, swift, upc

The linux kernel, for instance, is written in 'c89' circa 2022, use that in filters.

.TP
.B \-y, \-\-prefix_filter=PREFIX
Include PREFIXed classes.
Expand Down
90 changes: 90 additions & 0 deletions pahole.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,78 @@ static struct rb_root structures__tree = RB_ROOT;
static LIST_HEAD(structures__list);
static pthread_mutex_t structures_lock = PTHREAD_MUTEX_INITIALIZER;

static struct {
char *str;
int *entries;
int nr_entries;
} languages;

static int lang_id_cmp(const void *pa, const void *pb)
{
int a = *(int *)pa,
b = *(int *)pb;
return a - b;
}

static int parse_languages(void)
{
int nr_allocated = 4;
char *lang = languages.str;

languages.entries = malloc(sizeof(int) * nr_allocated);
if (languages.entries == NULL)
goto out_enomem;

while (1) {
char *sep = strchr(lang, ',');

if (sep)
*sep = '\0';

int id = lang__str2int(lang);

if (sep)
*sep = ',';

if (id < 0) {
fprintf(stderr, "pahole: unknown language \"%s\"\n", lang);
goto out_free;
}

if (languages.nr_entries >= nr_allocated) {
nr_allocated *= 2;
int *entries = realloc(languages.entries, nr_allocated);

if (entries == NULL)
goto out_enomem;

languages.entries = entries;
}

languages.entries[languages.nr_entries++] = id;

if (!sep)
break;

lang = sep + 1;
}

qsort(languages.entries, languages.nr_entries, sizeof(int), lang_id_cmp);

return 0;
out_enomem:
fprintf(stderr, "pahole: not enough memory to parse --lang\n");
out_free:
zfree(&languages.entries);
languages.nr_entries = 0;
return -1;
}

static bool languages__in(int lang)
{
return bsearch(&lang, languages.entries, languages.nr_entries, sizeof(int), lang_id_cmp) != NULL;
}

static int type__compare_members_types(struct type *a, struct cu *cu_a, struct type *b, struct cu *cu_b)
{
int ret = strcmp(type__name(a), type__name(b));
Expand Down Expand Up @@ -609,6 +681,12 @@ static void print_ordered_classes(void)

static struct cu *cu__filter(struct cu *cu)
{
if (languages.nr_entries) {
bool in = languages__in(cu->language);
if (!in)
return NULL;
}

if (cu__exclude_prefix != NULL &&
(cu->name == NULL ||
strncmp(cu__exclude_prefix, cu->name,
Expand Down Expand Up @@ -1137,6 +1215,7 @@ ARGP_PROGRAM_VERSION_HOOK_DEF = dwarves_print_version;
#define ARGP_skip_missing 332
#define ARGP_skip_encoding_btf_type_tag 333
#define ARGP_compile 334
#define ARGP_languages 335

static const struct argp_option pahole__options[] = {
{
Expand Down Expand Up @@ -1527,6 +1606,12 @@ static const struct argp_option pahole__options[] = {
.key = ARGP_skip_encoding_btf_type_tag,
.doc = "Do not encode TAGs in BTF."
},
{
.name = "lang",
.key = ARGP_languages,
.arg = "LANGUAGES",
.doc = "Only consider compilation units written in these languages"
},
{
.name = NULL,
}
Expand Down Expand Up @@ -1687,6 +1772,8 @@ static error_t pahole__options_parser(int key, char *arg,
conf_load.skip_missing = true; break;
case ARGP_skip_encoding_btf_type_tag:
conf_load.skip_encoding_btf_type_tag = true; break;
case ARGP_languages:
languages.str = arg; break;
default:
return ARGP_ERR_UNKNOWN;
}
Expand Down Expand Up @@ -3280,6 +3367,9 @@ int main(int argc, char *argv[])
goto out;
}

if (languages.str && parse_languages())
return rc;

if (class_name != NULL && stats_formatter == nr_methods_formatter) {
fputs("pahole: -m/nr_methods doesn't work with --class/-C, it shows all classes and the number of its methods\n", stderr);
return rc;
Expand Down

0 comments on commit 8ee3637

Please sign in to comment.