Skip to content

Commit 8ee3637

Browse files
committed
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>
1 parent c3f2fe2 commit 8ee3637

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed

man-pages/pahole.1

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,19 @@ Exclude PREFIXed classes.
368368
.B \-X, \-\-cu_exclude=PREFIX
369369
Exclude PREFIXed compilation units.
370370

371+
.TP
372+
.B \-\-lang=languages
373+
Only process compilation units built from source code written in the specified languages.
374+
375+
Supported languages:
376+
377+
ada83, ada95, bliss, c, c89, c99, c11, c++, c++03, c++11, c++14, cobol74,
378+
cobol85, d, dylan, fortran77, fortran90, fortran95, fortran03, fortran08,
379+
go, haskell, java, julia, modula2, modula3, objc, objc++, ocaml, opencl,
380+
pascal83, pli, python, renderscript, rust, swift, upc
381+
382+
The linux kernel, for instance, is written in 'c89' circa 2022, use that in filters.
383+
371384
.TP
372385
.B \-y, \-\-prefix_filter=PREFIX
373386
Include PREFIXed classes.

pahole.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,78 @@ static struct rb_root structures__tree = RB_ROOT;
129129
static LIST_HEAD(structures__list);
130130
static pthread_mutex_t structures_lock = PTHREAD_MUTEX_INITIALIZER;
131131

132+
static struct {
133+
char *str;
134+
int *entries;
135+
int nr_entries;
136+
} languages;
137+
138+
static int lang_id_cmp(const void *pa, const void *pb)
139+
{
140+
int a = *(int *)pa,
141+
b = *(int *)pb;
142+
return a - b;
143+
}
144+
145+
static int parse_languages(void)
146+
{
147+
int nr_allocated = 4;
148+
char *lang = languages.str;
149+
150+
languages.entries = malloc(sizeof(int) * nr_allocated);
151+
if (languages.entries == NULL)
152+
goto out_enomem;
153+
154+
while (1) {
155+
char *sep = strchr(lang, ',');
156+
157+
if (sep)
158+
*sep = '\0';
159+
160+
int id = lang__str2int(lang);
161+
162+
if (sep)
163+
*sep = ',';
164+
165+
if (id < 0) {
166+
fprintf(stderr, "pahole: unknown language \"%s\"\n", lang);
167+
goto out_free;
168+
}
169+
170+
if (languages.nr_entries >= nr_allocated) {
171+
nr_allocated *= 2;
172+
int *entries = realloc(languages.entries, nr_allocated);
173+
174+
if (entries == NULL)
175+
goto out_enomem;
176+
177+
languages.entries = entries;
178+
}
179+
180+
languages.entries[languages.nr_entries++] = id;
181+
182+
if (!sep)
183+
break;
184+
185+
lang = sep + 1;
186+
}
187+
188+
qsort(languages.entries, languages.nr_entries, sizeof(int), lang_id_cmp);
189+
190+
return 0;
191+
out_enomem:
192+
fprintf(stderr, "pahole: not enough memory to parse --lang\n");
193+
out_free:
194+
zfree(&languages.entries);
195+
languages.nr_entries = 0;
196+
return -1;
197+
}
198+
199+
static bool languages__in(int lang)
200+
{
201+
return bsearch(&lang, languages.entries, languages.nr_entries, sizeof(int), lang_id_cmp) != NULL;
202+
}
203+
132204
static int type__compare_members_types(struct type *a, struct cu *cu_a, struct type *b, struct cu *cu_b)
133205
{
134206
int ret = strcmp(type__name(a), type__name(b));
@@ -609,6 +681,12 @@ static void print_ordered_classes(void)
609681

610682
static struct cu *cu__filter(struct cu *cu)
611683
{
684+
if (languages.nr_entries) {
685+
bool in = languages__in(cu->language);
686+
if (!in)
687+
return NULL;
688+
}
689+
612690
if (cu__exclude_prefix != NULL &&
613691
(cu->name == NULL ||
614692
strncmp(cu__exclude_prefix, cu->name,
@@ -1137,6 +1215,7 @@ ARGP_PROGRAM_VERSION_HOOK_DEF = dwarves_print_version;
11371215
#define ARGP_skip_missing 332
11381216
#define ARGP_skip_encoding_btf_type_tag 333
11391217
#define ARGP_compile 334
1218+
#define ARGP_languages 335
11401219

11411220
static const struct argp_option pahole__options[] = {
11421221
{
@@ -1527,6 +1606,12 @@ static const struct argp_option pahole__options[] = {
15271606
.key = ARGP_skip_encoding_btf_type_tag,
15281607
.doc = "Do not encode TAGs in BTF."
15291608
},
1609+
{
1610+
.name = "lang",
1611+
.key = ARGP_languages,
1612+
.arg = "LANGUAGES",
1613+
.doc = "Only consider compilation units written in these languages"
1614+
},
15301615
{
15311616
.name = NULL,
15321617
}
@@ -1687,6 +1772,8 @@ static error_t pahole__options_parser(int key, char *arg,
16871772
conf_load.skip_missing = true; break;
16881773
case ARGP_skip_encoding_btf_type_tag:
16891774
conf_load.skip_encoding_btf_type_tag = true; break;
1775+
case ARGP_languages:
1776+
languages.str = arg; break;
16901777
default:
16911778
return ARGP_ERR_UNKNOWN;
16921779
}
@@ -3280,6 +3367,9 @@ int main(int argc, char *argv[])
32803367
goto out;
32813368
}
32823369

3370+
if (languages.str && parse_languages())
3371+
return rc;
3372+
32833373
if (class_name != NULL && stats_formatter == nr_methods_formatter) {
32843374
fputs("pahole: -m/nr_methods doesn't work with --class/-C, it shows all classes and the number of its methods\n", stderr);
32853375
return rc;

0 commit comments

Comments
 (0)