aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2022-04-25 14:23:20 -0300
committerArnaldo Carvalho de Melo <acme@redhat.com>2022-04-25 15:04:21 -0300
commit8ee363790b7437283c53090a85a9fec2f0b0fbc4 (patch)
treeb2df5da6a3c8c586b809bb2ab614643d5cb61e7a
parentc3f2fe2f6a81f13c618f675417f1d49c8d75ef99 (diff)
downloadpahole-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.113
-rw-r--r--pahole.c90
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.
diff --git a/pahole.c b/pahole.c
index 5ec26081..d8269c70 100644
--- a/pahole.c
+++ b/pahole.c
@@ -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;