diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2022-04-25 14:23:20 -0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2022-04-25 15:04:21 -0300 |
commit | 8ee363790b7437283c53090a85a9fec2f0b0fbc4 (patch) | |
tree | b2df5da6a3c8c586b809bb2ab614643d5cb61e7a | |
parent | c3f2fe2f6a81f13c618f675417f1d49c8d75ef99 (diff) | |
download | pahole-8ee363790b7437283c53090a85a9fec2f0b0fbc4.tar.gz |
pahole: Introduce --lang to ask for only compilation units written in 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 <acme@redhat.com>
-rw-r--r-- | man-pages/pahole.1 | 13 | ||||
-rw-r--r-- | pahole.c | 90 |
2 files changed, 103 insertions, 0 deletions
diff --git a/man-pages/pahole.1 b/man-pages/pahole.1 index ec83aa65..6a7aee3c 100644 --- a/man-pages/pahole.1 +++ b/man-pages/pahole.1 @@ -369,6 +369,19 @@ Exclude PREFIXed classes. 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. @@ -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)); @@ -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, @@ -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[] = { { @@ -1528,6 +1607,12 @@ static const struct argp_option pahole__options[] = { .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, } }; @@ -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; } @@ -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; |