7 - Support raw BTF as available in /sys/kernel/btf/vmlinux.
11 - When the sole argument passed isn't a file, take it as a class name:
15 - Do not require a class name to operate without a file name.
17 $ pahole # is equivalent to:
20 - Make --find_pointers_to consider unions:
22 $ pahole --find_pointers_to ehci_qh
24 - Make --contains and --find_pointers_to honour --unions
26 $ pahole --unions --contains inet_sock
28 - Add support for finding pointers to void:
30 $ pahole --find_pointers_to void
32 - Make --contains and --find_pointers_to to work with base types:
34 $ pahole --find_pointers_to 'short unsigned int'
36 - Make --contains look for more than just unions, structs:
38 $ pahole --contains raw_spinlock_t
40 - Consider unions when looking for classes containing some class:
42 $ pahole --contains tpacket_req
44 - Introduce --unions to consider just unions:
46 $ pahole --unions --sizes
47 $ pahole --unions --prefix tcp
48 $ pahole --unions --nr_members
50 - Fix -m/--nr_methods - Number of functions operating on a type pointer
56 - Add section about --hex + -E to locate offsets deep into sub structs.
58 - Add more information about BTF.
62 ----------------------------------
68 - Support raw BTF as available in /sys/kernel/btf/vmlinux
70 Be it automatically when no -F option is passed and
71 /sys/kernel/btf/vmlinux is available, or when /sys/kernel/btf/vmlinux is
72 passed as the filename to the tool, i.e.:
76 struct list_head * next; /* 0 8 */
77 struct list_head * prev; /* 8 8 */
79 /* size: 16, cachelines: 1, members: 2 */
80 /* last cacheline: 16 bytes */
82 $ strace -e openat pahole -C list_head |& grep /sys/kernel/btf/
83 openat(AT_FDCWD, "/sys/kernel/btf/vmlinux", O_RDONLY) = 3
85 $ pahole -C list_head /sys/kernel/btf/vmlinux
87 struct list_head * next; /* 0 8 */
88 struct list_head * prev; /* 8 8 */
90 /* size: 16, cachelines: 1, members: 2 */
91 /* last cacheline: 16 bytes */
95 If one wants to grab the matching vmlinux to use its DWARF info instead,
96 which is useful to compare the results with what we have from BTF, for
97 instance, its just a matter of using '-F dwarf'.
99 This in turn shows something that at first came as a surprise, but then
100 has a simple explanation:
102 For very common data structures, that will probably appear in all of the
103 DWARF CUs (Compilation Units), like 'struct list_head', using '-F dwarf'
106 $ perf stat -e cycles pahole -F btf -C list_head > /dev/null
108 Performance counter stats for 'pahole -F btf -C list_head':
112 0.023717300 seconds time elapsed
114 0.016474000 seconds user
115 0.007212000 seconds sys
117 $ perf stat -e cycles pahole -F dwarf -C list_head > /dev/null
119 Performance counter stats for 'pahole -F dwarf -C list_head':
123 0.006668904 seconds time elapsed
125 0.005562000 seconds user
126 0.001109000 seconds sys
130 But for something that is more specific to a subsystem, the DWARF loader
131 will have to process way more stuff till it gets to that struct:
133 $ perf stat -e cycles pahole -F dwarf -C tcp_sock > /dev/null
135 Performance counter stats for 'pahole -F dwarf -C tcp_sock':
137 31,579,795,238 cycles:u
139 8.332272930 seconds time elapsed
141 8.032124000 seconds user
142 0.286537000 seconds sys
146 While using the BTF loader the time should be constant, as it loads
147 everything from /sys/kernel/btf/vmlinux:
149 $ perf stat -e cycles pahole -F btf -C tcp_sock > /dev/null
151 Performance counter stats for 'pahole -F btf -C tcp_sock':
155 0.024102760 seconds time elapsed
157 0.012035000 seconds user
158 0.012046000 seconds sys
162 Above I used '-F btf' just to show that it can be used, but its not
163 really needed, i.e. those are equivalent:
165 $ strace -e openat pahole -F btf -C list_head |& grep /sys/kernel/btf/vmlinux
166 openat(AT_FDCWD, "/sys/kernel/btf/vmlinux", O_RDONLY) = 3
167 $ strace -e openat pahole -C list_head |& grep /sys/kernel/btf/vmlinux
168 openat(AT_FDCWD, "/sys/kernel/btf/vmlinux", O_RDONLY) = 3
171 The btf_raw__load() function that ends up being grafted into the
172 preexisting btf_elf routines was based on libbpf's btf_load_raw().
176 - When the sole argument passed isn't a file, take it as a class name.
178 With that it becomes as compact as it gets for kernel data structures,
179 just state the name of the struct and it'll try to find that as a file,
180 not being a file it'll use /sys/kernel/btf/vmlinux and the argument as a
181 list of structs, i.e.:
183 $ pahole skb_ext,list_head
185 struct list_head * next; /* 0 8 */
186 struct list_head * prev; /* 8 8 */
188 /* size: 16, cachelines: 1, members: 2 */
189 /* last cacheline: 16 bytes */
192 refcount_t refcnt; /* 0 4 */
193 u8 offset[3]; /* 4 3 */
195 char data[]; /* 8 0 */
197 /* size: 8, cachelines: 1, members: 4 */
198 /* last cacheline: 8 bytes */
202 struct hlist_node * next; /* 0 8 */
203 struct hlist_node * * pprev; /* 8 8 */
205 /* size: 16, cachelines: 1, members: 2 */
206 /* last cacheline: 16 bytes */
210 Of course -C continues to work:
212 $ pahole -C inode | tail
213 __u32 i_fsnotify_mask; /* 556 4 */
214 struct fsnotify_mark_connector * i_fsnotify_marks; /* 560 8 */
215 struct fscrypt_info * i_crypt_info; /* 568 8 */
216 /* --- cacheline 9 boundary (576 bytes) --- */
217 struct fsverity_info * i_verity_info; /* 576 8 */
218 void * i_private; /* 584 8 */
220 /* size: 592, cachelines: 10, members: 53 */
221 /* last cacheline: 16 bytes */
225 - Add support for finding pointers to void, e.g.:
227 $ pahole --find_pointers_to void --prefix tcp
228 tcp_md5sig_pool: scratch
229 $ pahole tcp_md5sig_pool
230 struct tcp_md5sig_pool {
231 struct ahash_request * md5_req; /* 0 8 */
232 void * scratch; /* 8 8 */
234 /* size: 16, cachelines: 1, members: 2 */
235 /* last cacheline: 16 bytes */
239 - Make --contains and --find_pointers_to to work with base types
241 I.e. with plain 'int', 'long', 'short int', etc:
243 $ pahole --find_pointers_to 'short unsigned int'
244 uv_hub_info_s: socket_to_node
245 uv_hub_info_s: socket_to_pnode
246 uv_hub_info_s: pnode_to_socket
247 vc_data: vc_screenbuf
248 vc_data: vc_translate
250 ext4_sb_info: s_mb_offsets
251 $ pahole ext4_sb_info | 'sort unsigned int'
252 bash: sort unsigned int: command not found...
255 $ pahole ext4_sb_info | grep 'sort unsigned int'
256 $ pahole ext4_sb_info | grep 'short unsigned int'
257 short unsigned int s_mount_state; /* 160 2 */
258 short unsigned int s_pad; /* 162 2 */
259 short unsigned int * s_mb_offsets; /* 664 8 */
260 $ pahole --contains 'short unsigned int'
266 fsnotify_mark_connector
273 - Make --contains look for more than just unions, structs, look for
274 typedefs, enums and types that descend from 'struct type':
276 So now we can do more interesting queries, lets see, what are the data
277 structures that embed a raw spinlock in the linux kernel?
279 $ pahole --contains raw_spinlock_t
293 Look at the csets comments to see more examples.
295 - Make --contains and --find_pointers_to honour --unions
297 I.e. when looking for unions or structs that contains/embeds or looking
298 for unions/structs that have pointers to a given type.
302 $ pahole --contains inet_sock
308 $ pahole --unions --contains inet_sock
311 We have structs embedding 'struct inet_sock', but no unions doing that.
313 - Make --find_pointers_to consider unions
317 $ pahole --find_pointers_to ehci_qh
318 ehci_hcd: qh_scan_next
325 $ pahole -C ehci_shadow
327 struct ehci_qh * qh; /* 0 8 */
328 struct ehci_itd * itd; /* 0 8 */
329 struct ehci_sitd * sitd; /* 0 8 */
330 struct ehci_fstn * fstn; /* 0 8 */
331 __le32 * hw_next; /* 0 8 */
332 void * ptr; /* 0 8 */
338 $ pahole --find_pointers_to ehci_qh
339 ehci_hcd: qh_scan_next
345 - Consider unions when looking for classes containing some class:
349 $ pahole --contains tpacket_req
353 Wasn't working, but should be considered with --contains/-i:
355 $ pahole -C tpacket_req_u
356 union tpacket_req_u {
357 struct tpacket_req req; /* 0 16 */
358 struct tpacket_req3 req3; /* 0 28 */
362 - Introduce --unions to consider just unions
364 Most filters can be used together with it, for instance to see the
365 biggest unions in the kernel:
367 $ pahole --unions --sizes | sort -k2 -nr | head
371 autofs_v5_packet_union 304 0
372 autofs_packet_union 272 0
373 pptp_ctrl_union 208 0
374 acpi_parse_object 200 0
375 acpi_descriptor 200 0
377 phy_configure_opts 112 0
380 Or just some unions that have some specific prefix:
382 $ pahole --unions --prefix tcp
384 struct in_addr a4; /* 0 4 */
385 struct in6_addr a6; /* 0 16 */
388 struct tcphdr hdr; /* 0 20 */
389 __be32 words[5]; /* 0 20 */
392 struct tcpvegas_info vegas; /* 0 16 */
393 struct tcp_dctcp_info dctcp; /* 0 16 */
394 struct tcp_bbr_info bbr; /* 0 20 */
398 What are the biggest unions in terms of number of members?
400 $ pahole --unions --nr_members | sort -k2 -nr | head
401 security_list_options 218
403 acpi_resource_data 29
404 acpi_operand_object 26
408 ethtool_flow_union 14
413 If you want to script most of the queries can change the separator:
415 $ pahole --unions --nr_members -t, | sort -t, -k2 -nr | head
416 security_list_options,218
418 acpi_resource_data,29
419 acpi_operand_object,26
423 ethtool_flow_union,14
428 - Fix -m/--nr_methods - Number of functions operating on a type pointer
430 We had to use the same hack as in pfunct, as implemented in ccf3eebfcd9c
431 ("btf_loader: Add support for BTF_KIND_FUNC"), will hide that 'struct
432 ftype' (aka function prototype) indirection behind the parameter
433 iterator (function__for_each_parameter).
435 For now, here is the top 10 Linux kernel data structures in terms of
436 number of functions receiving as one of its parameters a pointer to it,
437 using /sys/kernel/btf/vmlinux to look at all the vmlinux types and
438 functions (the ones visible in kallsyms, but with the parameters and its
441 $ pahole -m | sort -k2 -nr | head
453 $ pahole --help |& grep -- -m
454 -m, --nr_methods show number of methods
457 - Do not require a class name to operate without a file name
459 Since we default to operating on the running kernel data structures, we
460 should make the default to, with no options passed, to pretty print all
461 the running kernel data structures, or do what was asked in terms of
462 number of members, size of structs, etc, i.e.:
464 # pahole --help |& head
465 Usage: pahole [OPTION...] FILE
467 -a, --anon_include include anonymous classes
468 -A, --nested_anon_include include nested (inside other structs) anonymous
470 -B, --bit_holes=NR_HOLES Show only structs at least NR_HOLES bit holes
471 -c, --cacheline_size=SIZE set cacheline size to SIZE
472 --classes_as_structs Use 'struct' when printing classes
473 -C, --class_name=CLASS_NAME Show just this class
474 -d, --recursive recursive mode, affects several other flags
477 Continues working as before, but if you do:
481 It will work just as if you did:
485 and that vmlinux file is the running kernel vmlinux.
487 And since the default now is to read BTF info, then it will do all its
488 operations on /sys/kernel/btf/vmlinux, when present, i.e. want to know
489 what are the fattest data structures in the running kernel:
491 # pahole -s | sort -k2 -nr | head
494 cpu_entry_area 217088 0
496 saved_cmdlines_buffer 131104 1
497 debug_store_buffers 131072 0
504 How many data structures in the running kernel vmlinux area embbed
507 # pahole -i list_head | wc -l
511 Lets see some of those?
513 # pahole -C fsnotify_event
514 struct fsnotify_event {
515 struct list_head list; /* 0 16 */
516 struct inode * inode; /* 16 8 */
518 /* size: 24, cachelines: 1, members: 2 */
519 /* last cacheline: 24 bytes */
521 # pahole -C audit_chunk
523 struct list_head hash; /* 0 16 */
524 long unsigned int key; /* 16 8 */
525 struct fsnotify_mark * mark; /* 24 8 */
526 struct list_head trees; /* 32 16 */
527 int count; /* 48 4 */
529 /* XXX 4 bytes hole, try to pack */
531 atomic_long_t refs; /* 56 8 */
532 /* --- cacheline 1 boundary (64 bytes) --- */
533 struct callback_head head; /* 64 16 */
534 struct node owners[]; /* 80 0 */
536 /* size: 80, cachelines: 2, members: 8 */
537 /* sum members: 76, holes: 1, sum holes: 4 */
538 /* last cacheline: 16 bytes */