btf_encoder: handle .BTF_ids section endianness
[dwarves.git] / changes-v1.17
blob8999bdf348e5095f0df5110e5583b94d15540239
1 v1.17 changes:
3 tl;dr:
5 BTF loader:
7   - Support raw BTF as available in /sys/kernel/btf/vmlinux.
9 pahole:
11   - When the sole argument passed isn't a file, take it as a class name:
13      $ pahole sk_buff
15   - Do not require a class name to operate without a file name.
17       $ pahole          # is equivalent to:
18       $ pahole vmlinux
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
52       $ pahole --nr_methods
54 man-pages:
56   - Add section about --hex + -E to locate offsets deep into sub structs.
58   - Add more information about BTF.
60   - Add some examples.
62 ----------------------------------
64 I want the details:
66 btf loader:
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.:
74       $ pahole -C list_head
75       struct list_head {
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 */
81       };
82       $ strace -e openat pahole -C list_head |& grep /sys/kernel/btf/
83       openat(AT_FDCWD, "/sys/kernel/btf/vmlinux", O_RDONLY) = 3
84       $
85       $ pahole -C list_head /sys/kernel/btf/vmlinux
86       struct list_head {
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 */
92       };
93       $
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'
104     is faster:
106       $ perf stat -e cycles pahole -F btf -C list_head > /dev/null
108        Performance counter stats for 'pahole -F btf -C list_head':
110               45,722,518      cycles:u
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':
121               14,170,321      cycles:u
123              0.006668904 seconds time elapsed
125              0.005562000 seconds user
126              0.001109000 seconds sys
128       $
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
144       $
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':
153               48,823,488      cycles:u
155              0.024102760 seconds time elapsed
157              0.012035000 seconds user
158              0.012046000 seconds sys
160       $
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
169       $
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().
174 pahole:
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
184       struct 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 */
190       };
191       struct skb_ext {
192             refcount_t                 refcnt;               /*     0     4 */
193             u8                         offset[3];            /*     4     3 */
194             u8                         chunks;               /*     7     1 */
195             char                       data[];               /*     8     0 */
197             /* size: 8, cachelines: 1, members: 4 */
198             /* last cacheline: 8 bytes */
199       };
200       $ pahole hlist_node
201       struct hlist_node {
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 */
207       };
208       $
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 */
222       };
223       $
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 */
236       };
237       $
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
249       filter_pred: ops
250       ext4_sb_info: s_mb_offsets
251       $ pahole ext4_sb_info | 'sort unsigned int'
252       bash: sort unsigned int: command not found...
253       ^[^C
254       $
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'
261       apm_info
262       desc_ptr
263       thread_struct
264       mpc_table
265       mpc_intsrc
266       fsnotify_mark_connector
267       <SNIP>
268       sock_fprog
269       blk_mq_hw_ctx
270       skb_shared_info
271       $
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
280       task_struct
281       rw_semaphore
282       hrtimer_cpu_base
283       prev_cputime
284       percpu_counter
285       ratelimit_state
286       perf_event_context
287       task_delay_info
288       <SNIP>
289       lpm_trie
290       bpf_queue_stack
291       $
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.
300     E.g:
302       $ pahole --contains inet_sock
303       sctp_sock
304       inet_connection_sock
305       raw_sock
306       udp_sock
307       raw6_sock
308       $ pahole --unions --contains inet_sock
309       $
311     We have structs embedding 'struct inet_sock', but no unions doing that.
313   - Make --find_pointers_to consider unions
315     I.e.:
317       $ pahole --find_pointers_to ehci_qh
318       ehci_hcd: qh_scan_next
319       ehci_hcd: async
320       ehci_hcd: dummy
321       $
323     Wasn't considering:
325       $ pahole -C ehci_shadow
326       union 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 */
333       };
334       $
336     Fix it:
338       $ pahole --find_pointers_to ehci_qh
339       ehci_hcd: qh_scan_next
340       ehci_hcd: async
341       ehci_hcd: dummy
342       ehci_shadow: qh
343       $
345   - Consider unions when looking for classes containing some class:
347     I.e.:
349       $ pahole --contains tpacket_req
350       tpacket_req_u
351       $
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 */
359       };
360       $
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
368       thread_union            16384 0
369       swap_header              4096 0
370       fpregs_state             4096 0
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
376       bpf_attr                  120 0
377       phy_configure_opts        112 0
378       $
380     Or just some unions that have some specific prefix:
382       $ pahole --unions --prefix tcp
383       union tcp_md5_addr {
384             struct in_addr             a4;                 /*     0     4 */
385             struct in6_addr            a6;                 /*     0    16 */
386       };
387       union tcp_word_hdr {
388             struct tcphdr              hdr;                /*     0    20 */
389             __be32                     words[5];           /*     0    20 */
390       };
391       union tcp_cc_info {
392             struct tcpvegas_info       vegas;              /*     0    16 */
393             struct tcp_dctcp_info      dctcp;              /*     0    16 */
394             struct tcp_bbr_info        bbr;                /*     0    20 */
395       };
396       $
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
402       aml_resource           36
403       acpi_resource_data     29
404       acpi_operand_object    26
405       iwreq_data             18
406       sctp_params            15
407       ib_flow_spec           14
408       ethtool_flow_union     14
409       pptp_ctrl_union        13
410       bpf_attr               12
411       $
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
417       aml_resource,36
418       acpi_resource_data,29
419       acpi_operand_object,26
420       iwreq_data,18
421       sctp_params,15
422       ib_flow_spec,14
423       ethtool_flow_union,14
424       pptp_ctrl_union,13
425       bpf_attr,12
426       $
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
439     types):
441       $ pahole -m | sort -k2 -nr | head
442       device        955
443       sock          568
444       sk_buff       541
445       task_struct   437
446       inode         421
447       pci_dev       390
448       page          351
449       net_device    347
450       file          315
451       net           312
452       $
453       $ pahole --help |& grep -- -m
454         -m, --nr_methods           show number of methods
455       $
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
469                                    classes
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
475       #
477     Continues working as before, but if you do:
479       pahole
481     It will work just as if you did:
483       pahole vmlinux
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
492       cmp_data      290904  1
493       dec_data      274520  1
494       cpu_entry_area        217088  0
495       pglist_data   172928  4
496       saved_cmdlines_buffer 131104  1
497       debug_store_buffers   131072  0
498       hid_parser    110848  1
499       hid_local     110608  0
500       zonelist      81936   0
501       e820_table    64004   0
502       #
504     How many data structures in the running kernel vmlinux area embbed
505     'struct list_head'?
507       # pahole -i list_head | wc -l
508       260
509       #
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 */
520       };
521       # pahole -C audit_chunk
522       struct 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 */
539       };
540       #