Commit Graph

1370 Commits

Author SHA1 Message Date
Arnaldo Carvalho de Melo e709afe6a9 dwarves: Prep v1.17
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-03-13 16:36:02 -03:00
Arnaldo Carvalho de Melo f14426e410 docs: Add command line to generate tarball with a prefix
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-03-12 16:55:15 -03:00
Arnaldo Carvalho de Melo 0b2621d426 dwarves: Avoid truncation when concatenating paths for dir entries
To cope with this warning on s390x:

  /usr/bin/cc -DDWARVES_VERSION=\"v1.16\" -D_GNU_SOURCE -Ddwarves_EXPORTS -I/builddir/build/BUILD/dwarves-1.16 -I/builddir/build/BUILD/dwarves-1.16/lib/bpf/include/uapi  -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=zEC12 -mtune=z13 -fasynchronous-unwind-tables -fstack-clash-protection -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Werror -ggdb -O2 -fPIC   -o CMakeFiles/dwarves.dir/libctf.c.o   -c /builddir/build/BUILD/dwarves-1.16/libctf.c
  /builddir/build/BUILD/dwarves-1.16/dwarves.h: In function 'cus__load_dir':
  /builddir/build/BUILD/dwarves-1.16/dwarves.c:1663:44: error: '%s' directive output may be truncated writing up to 255 bytes into a region of size between 0 and 4095 [-Werror=format-truncation=]
   1663 |   snprintf(pathname, sizeof(pathname), "%s/%s",
        |                                            ^~
  In file included from /usr/include/stdio.h:867,
                   from /builddir/build/BUILD/dwarves-1.16/dwarves.c:18:
  /usr/include/bits/stdio2.h:67:10: note: '__builtin___snprintf_chk' output between 2 and 4352 bytes into a destination of size 4096
     67 |   return __builtin___snprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
        |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     68 |        __bos (__s), __fmt, __va_arg_pack ());
        |        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /builddir/build/BUILD/dwarves-1.16/dwarves.c:1663:44: error: '%s' directive output may be truncated writing up to 255 bytes into a region of size between 0 and 4095 [-Werror=format-truncation=]
   1663 |   snprintf(pathname, sizeof(pathname), "%s/%s",
        |                                            ^~
  In file included from /usr/include/stdio.h:867,
                   from /builddir/build/BUILD/dwarves-1.16/dwarves.c:18:
  /usr/include/bits/stdio2.h:67:10: note: '__builtin___snprintf_chk' output between 2 and 4352 bytes into a destination of size 4096

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-02-12 16:28:49 -03:00
Arnaldo Carvalho de Melo d7b3510795 dwarves: Don't use conf if its NULL in cus__load_running_kernel()
Don't use it if NULL, fixing a segfault with dtagnames as reported in:

https://bugzilla.redhat.com/show_bug.cgi?id=1795379

Reported-by: Jan Pokorný <jpokorny@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-02-12 16:10:09 -03:00
Arnaldo Carvalho de Melo dde3eb086d dwarves: Make list__for_all_tags() more robust
Return if passed a zeroed list or an empty one.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-02-12 16:04:31 -03:00
Andrii Nakryiko 081f3618a7 dwarves: Add -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 to build libbpf
We need that as the fix in upstream libbpf is in the
tools/lib/bpf/Makefile, that isn't used when building libbpf as part of
pahole, see:

  "Makefile: back-port _FILE_OFFSET_BITS=64 and _LARGEFILE64_SOURCE to Makefile"
  4a50ceb043

That refers to this in the kernel sources:

  71dd77fd4bf7 ("libbpf: use LFS (_FILE_OFFSET_BITS) instead of direct mmap2 syscall")

Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Julia Kartseva <hex@fb.com>
Cc: Yonghong Song <yhs@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-02-03 08:52:26 +01:00
Arnaldo Carvalho de Melo e8f43a4963 libbpf: Get latest libbpf
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-02-03 08:43:10 +01:00
Jason A. Donenfeld de84ae36c7 cmake: libebl was merged into libdw
Since elfutils 178, libebl is now part of libdw, so searching for libebl
always fails. Simply remove it from the search.

Reviewer notes:

I even built dwarves with the patch against and old elfutils-0.176 and a
new elfutils-0.178 to double check. Builds fine with both.

With elfutils-0.178 pahole even automagically works with the new
debuginfo-client support.  See

https://sourceware.org/elfutils/Debuginfod.html

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Reviewed-by: Mark Wielaard <mark@klomp.org>
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-02-03 08:42:13 +01:00
Arnaldo Carvalho de Melo 290b8fdbda pahole: Improve --contains --recursive a bit
Its not yet correct, misses cases where a top level struct doesn't have
the contained type but some of its substructs have, i.e. right now it
looks if the top level struct has the looked up container type and if it
has, it prints its name and then goes to look at all its members if some
has the looked up container type, recursively.

It should go all the way down, even when a struct doesn't have the
looked up contained type some of its members may have.

So for now its better to use 'pahole -E struct_name | less' and then
search for the type, will be fixed after DevConf.cz 2020 :-)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-21 12:34:42 -03:00
Arnaldo Carvalho de Melo 3d5be866e5 pahole: Fill 'tab' with spaces earlier
We need it in --recursive --contains, otherwise we don't ident.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-21 12:32:12 -03:00
Petr Vandrovec 88674f0395 gobuffer: Do not crash on object without any public symbols
pahole -J .tmp_linux.btf during Linux build process always crashes
on my system.

Problem is that when gobuffer is initialized via gobuffer__init(),
it is in state where 'index' (AKA its size) is set to 1, but
'entries' is NULL.

State corrects itself if 'gobuffer__add()' is invoked, as that
will allocate buffer (even if added len == 0).  But if __add()
is never invoked because only anonymous symbols are present,
one ends up with gobuffer that crashes gobuffer__copy.

Instead of allocating single-byte buffer always I opted for
checking if gobuffer entries is NULL before use in copy and
compress - gobuffer__init() would need prototype change to
report malloc failures, and it seems unnecessary to allocate
memory always - even if file does not have any symbols after
all.

(gdb) bt
 #0  __memmove_sse2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:287
 #1  0x00007f2f2c1ec2ee in btf_elf__encode (btfe=0x5654e31e2e30, flags=flags@entry=0 '\000') at libbtf.c:750
 #2  0x00007f2f2c1e9af0 in btf_encoder__encode () at btf_encoder.c:164
 #3  0x00005654e2407599 in main (argc=3, argv=0x7ffcd8783f18) at pahole.c:1344
(gdb) frame 1
 #1  0x00007f2f2c1ec2ee in btf_elf__encode (btfe=0x5654e31e2e30, flags=flags@entry=0 '\000') at libbtf.c:750
750             gobuffer__copy(btfe->strings, btf_elf__nohdr_data(btfe) + hdr->str_off);
(gdb) print btfe->strings
$1 = (struct gobuffer *) 0x5654e31db2c8
(gdb) print *btfe->strings
$2 = {entries = 0x0, nr_entries = 0, index = 1, allocated_size = 0}
(gdb) print btfe->types
$3 = {entries = 0x5654e31e2ef0 "", nr_entries = 1, index = 16, allocated_size = 8192}
(gdb) x /16bx btfe->types.entries
0x5654e31e2ef0: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x01
0x5654e31e2ef8: 0x04    0x00    0x00    0x00    0x20    0x00    0x00    0x00

Signed-off-by: Petr Vandrovec <petr@vmware.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-17 13:54:15 -03:00
Domenico Andreoli cb17f94f46 Add changes-v1.16 to the MANIFEST file
Signed-off-by: Domenico Andreoli <domenico.andreoli@linux.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-17 13:34:37 -03:00
Julia Kartseva 32a19e044c pahole: Fix changelog date in dwarves.spec
Signed-off-by: Julia Kartseva <hex@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-17 13:34:33 -03:00
Arnaldo Carvalho de Melo 9b09f578b7 pahole: Initialize var to silence -Werror=maybe-uninitialized on gcc version 4.8.5 20150623
That str variable _will_ be initialized at that point, but lets set it
to NULL to silence gcc version 4.8.5 20150623.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-17 12:40:37 -03:00
Arnaldo Carvalho de Melo 277c2b3d1b man-pages: Add section about --hex + -E to locate offsets deep into sub structs
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-16 12:10:54 -03:00
Arnaldo Carvalho de Melo 812c980b3f man-pages: Update some info, expand BTF info, add some EXAMPLES
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-16 11:36:20 -03:00
Arnaldo Carvalho de Melo e0942c7b03 pahole: Add support for finding pointers to void
$ pahole --find_pointers_to void --prefix tcp
  tcp_md5sig_pool: scratch
  $ pahole tcp_md5sig_pool
  struct tcp_md5sig_pool {
  	struct ahash_request *     md5_req;              /*     0     8 */
  	void *                     scratch;              /*     8     8 */

  	/* size: 16, cachelines: 1, members: 2 */
  	/* last cacheline: 16 bytes */
  };
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-15 16:33:41 -03:00
Arnaldo Carvalho de Melo 6a326e9308 pahole: Make --contains and --find_pointers_to to work with base types
I.e. with plain 'int', 'long', 'short int', etc:

  $ pahole --find_pointers_to 'short unsigned int'
  uv_hub_info_s: socket_to_node
  uv_hub_info_s: socket_to_pnode
  uv_hub_info_s: pnode_to_socket
  vc_data: vc_screenbuf
  vc_data: vc_translate
  filter_pred: ops
  ext4_sb_info: s_mb_offsets
  $ pahole ext4_sb_info | 'sort unsigned int'
  bash: sort unsigned int: command not found...
  ^[^C
  $
  $ pahole ext4_sb_info | grep 'sort unsigned int'
  $ pahole ext4_sb_info | grep 'short unsigned int'
  	short unsigned int         s_mount_state;        /*   160     2 */
  	short unsigned int         s_pad;                /*   162     2 */
  	short unsigned int *       s_mb_offsets;         /*   664     8 */
  $ pahole --contains 'short unsigned int'
  apm_info
  desc_ptr
  thread_struct
  mpc_table
  mpc_intsrc
  hrtimer_cpu_base
  sched_rt_entity
  io_context
  inode
  tlb_state
  kernfs_node
  bug_entry
  mempolicy
  key
  blk_plug
  gendisk
  bio
  trace_entry
  bio_integrity_payload
  request
  queue_limits
  blk_integrity_iter
  ifmap
  winsize
  net_device
  rpc_task
  rpc_wait_queue
  dst_ops
  dst_entry
  tcmsg
  sock_common
  nfs_fh
  posix_acl_entry
  nfs_server
  pci_dev
  pci_bus
  kernel_vm86_regs
  user_i387_struct
  fs_parameter_spec
  serial_struct
  mpc_lintsrc
  uv_hub_info_s
  hpet_data
  bau_pq_entry
  uvhub_desc
  bau_control
  vc_data
  ipc_ids
  ww_acquire_ctx
  fsnotify_mark_connector
  sock_fprog
  blk_mq_hw_ctx
  skb_shared_info
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-15 16:23:34 -03:00
Arnaldo Carvalho de Melo 3c1a9a3329 pahole: Make --contains look for more than just unions, structs
Look for typedefs, enums and types that descend from 'struct type', that
is:

  static inline int tag__is_type(const struct tag *tag)
  {
          return tag__is_union(tag)   ||
                 tag__is_struct(tag)  ||
                 tag__is_typedef(tag) ||
                 tag__is_rvalue_reference_type(tag) ||
                 tag__is_enumeration(tag);
  }

So now we can do more interesting queries, lets see, what are the data
structures that embed a raw spinlock in the linux kernel?

  $ pahole --contains raw_spinlock_t
  task_struct
  rw_semaphore
  hrtimer_cpu_base
  prev_cputime
  percpu_counter
  ratelimit_state
  perf_event_context
  task_delay_info
  perf_cpu_context
  perf_addr_filters_head
  fprop_local_percpu
  ld_semaphore
  er_account
  intel_excl_cntrs
  perf_amd_iommu
  irq_desc
  irq_chip_generic
  nmi_desc
  ssb_state
  semaphore
  uv_hub_nmi_s
  kretprobe
  swait_queue_head
  kvm_task_sleep_head
  kthread_worker
  root_domain
  cpudl
  rt_bandwidth
  dl_bandwidth
  dl_bw
  cfs_bandwidth
  rq
  rt_rq
  sugov_policy
  rt_mutex
  rcu_node
  rcu_data
  rcu_state
  timer_base
  cpu_stopper
  trace_array
  ring_buffer_per_cpu
  pcpu_freelist_head
  bpf_lru_list
  bpf_lru_locallist
  bucket
  lpm_trie
  bpf_queue_stack
  $

This is using the /sys/kernel/btf/vmlinux file, so it is really fast:

  $ time pahole --contains raw_spinlock_t > /dev/null

  real	0m0.034s
  user	0m0.023s
  sys	0m0.011s
  $

Look at one of those, say:

  $ pahole bpf_queue_stack
  struct bpf_queue_stack {
  	struct bpf_map             map;                  /*     0   256 */

  	/* XXX last struct has 40 bytes of padding */

  	/* --- cacheline 4 boundary (256 bytes) --- */
  	raw_spinlock_t             lock;                 /*   256     4 */
  	u32                        head;                 /*   260     4 */
  	u32                        tail;                 /*   264     4 */
  	u32                        size;                 /*   268     4 */
  	char                       elements[];           /*   272     0 */

  	/* size: 320, cachelines: 5, members: 6 */
  	/* padding: 48 */
  	/* paddings: 1, sum paddings: 40 */
  };
  $

But you may be intested only in RCU stuff, so...

  $ pahole --contains raw_spinlock_t --prefix rcu
  rcu_node
  rcu_data
  rcu_state
  $ pahole rcu_node,rcu_data,rcu_state | egrep '(^struct|raw_spinlock_t)'
  struct rcu_data {
  	raw_spinlock_t             nocb_lock;            /*   288     4 */
  	raw_spinlock_t             nocb_bypass_lock;     /*   384     4 */
  	raw_spinlock_t             nocb_gp_lock;         /*   448     4 */
  struct rcu_node {
  	raw_spinlock_t             lock;                 /*     0     4 */
  	raw_spinlock_t             fqslock;              /*   320     4 */
  struct rcu_state {
  	raw_spinlock_t             ofl_lock;             /*  3328     4 */
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-15 13:47:49 -03:00
Arnaldo Carvalho de Melo ded5d36f9c dwarves: Introduce cu__find_type_by_name
To look at all the 'struct type' descendants, like enums, typedefs,
structs, unions, etc.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-15 13:45:47 -03:00
Arnaldo Carvalho de Melo 88d99562e5 pahole: Add --structs to ask just for structs, counterpart of --unions
The default is to show structs and unions, if just structs should be
considered, use --structs, just don't use it together with --unions or
nothing will be shown 8-)

  $ pahole --find_pointers_to ehci_qh
  ehci_hcd: qh_scan_next
  ehci_hcd: async
  ehci_hcd: dummy
  ehci_shadow: qh
  $ pahole --structs --find_pointers_to ehci_qh
  ehci_hcd: qh_scan_next
  ehci_hcd: async
  ehci_hcd: dummy
  $ pahole --unions --find_pointers_to ehci_qh
  ehci_shadow: qh
  $ pahole --structs --unions --find_pointers_to ehci_qh
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-15 12:41:28 -03:00
Arnaldo Carvalho de Melo 0b444cf111 pahole: Make --contains and --find_pointers_to honour --unions
I.e. when looking for unions or structs that contains/embeds or looking
for unions/structs that have pointers to a given type.

E.g:

  $ pahole --contains inet_sock
  sctp_sock
  inet_connection_sock
  raw_sock
  udp_sock
  raw6_sock
  $ pahole --unions --contains inet_sock
  $

We have structs embedding 'struct inet_sock', but no unions doing that.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-15 12:32:16 -03:00
Arnaldo Carvalho de Melo a8a7e605bb pahole: Make --find_pointers_to consider unions
I.e.:

  $ pahole --find_pointers_to ehci_qh
  ehci_hcd: qh_scan_next
  ehci_hcd: async
  ehci_hcd: dummy
  $

Wasn't considering:

  $ pahole -C ehci_shadow
  union ehci_shadow {
  	struct ehci_qh *           qh;                 /*     0     8 */
  	struct ehci_itd *          itd;                /*     0     8 */
  	struct ehci_sitd *         sitd;               /*     0     8 */
  	struct ehci_fstn *         fstn;               /*     0     8 */
  	__le32 *                   hw_next;            /*     0     8 */
  	void *                     ptr;                /*     0     8 */
  };
  $

Fix it:

  $ pahole --find_pointers_to ehci_qh
  ehci_hcd: qh_scan_next
  ehci_hcd: async
  ehci_hcd: dummy
  ehci_shadow: qh
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-15 12:31:47 -03:00
Arnaldo Carvalho de Melo 0dc327e382 pahole: Consider unions when looking for classes containing some class
I.e.:

  $ pahole --contains tpacket_req
  tpacket_req_u
  $

Wasn't working, but should be considered with --contains/-i:

  $ pahole -C tpacket_req_u
  union tpacket_req_u {
  	struct tpacket_req         req;                /*     0    16 */
  	struct tpacket_req3        req3;               /*     0    28 */
  };
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-15 12:31:47 -03:00
Arnaldo Carvalho de Melo 3661f17d0b pahole: Introduce --unions to consider just unions
Most filters can be used together with it, for instance to see the
biggest unions in the kernel:

  $ pahole --unions --sizes | sort -k2 -nr | head
  thread_union            16384 0
  swap_header              4096 0
  fpregs_state             4096 0
  autofs_v5_packet_union    304 0
  autofs_packet_union       272 0
  pptp_ctrl_union           208 0
  acpi_parse_object         200 0
  acpi_descriptor           200 0
  bpf_attr                  120 0
  phy_configure_opts        112 0
  $

Or just some unions that have some specific prefix:

  $ pahole --unions --prefix tcp
  union tcp_md5_addr {
  	struct in_addr             a4;                 /*     0     4 */
  	struct in6_addr            a6;                 /*     0    16 */
  };
  union tcp_word_hdr {
  	struct tcphdr              hdr;                /*     0    20 */
  	__be32                     words[5];           /*     0    20 */
  };
  union tcp_cc_info {
  	struct tcpvegas_info       vegas;              /*     0    16 */
  	struct tcp_dctcp_info      dctcp;              /*     0    16 */
  	struct tcp_bbr_info        bbr;                /*     0    20 */
  };
  $

What are the biggest unions in terms of number of members?

  $ pahole --unions --nr_members | sort -k2 -nr | head
  security_list_options 218
  aml_resource		 36
  acpi_resource_data	 29
  acpi_operand_object	 26
  iwreq_data		 18
  sctp_params		 15
  ib_flow_spec		 14
  ethtool_flow_union	 14
  pptp_ctrl_union	 13
  bpf_attr		 12
  $

If you want to script most of the queries can change the separator:

  $ pahole --unions --nr_members -t, | sort -t, -k2 -nr | head
  security_list_options,218
  aml_resource,36
  acpi_resource_data,29
  acpi_operand_object,26
  iwreq_data,18
  sctp_params,15
  ib_flow_spec,14
  ethtool_flow_union,14
  pptp_ctrl_union,13
  bpf_attr,12
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-15 12:31:47 -03:00
Arnaldo Carvalho de Melo 2dd09c6171 pahole: union have no holes, fix --sizes formatter
When we started supporting unions in pahole some corner cases where
classes were expected needed fixing, this was one such case, that
printed bogus number of holes when handling unions, that is represented
as a 'struct type', that doesn't have ->nr_holes, just 'struct class'
that is has 'struct type' as its first member, i.e. extends it.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-15 12:31:47 -03:00
Arnaldo Carvalho de Melo 6c29cca8c2 pahole: Don't consider unions for options that only make sense for structs
I.e. no point in looking for holes in unions.

Now 'pahole -H 10' will only show the structs with 10 or more alignment
holes, not those + all unions.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-15 12:31:42 -03:00
Arnaldo Carvalho de Melo dcba200367 pahole: When the sole argument passed isn't a file, take it as a class name
With that it becomes as compact as it gets for kernel data structures,
just state the name of the struct and it'll try to find that as a file,
not being a file it'll use /sys/kernel/btf/vmlinux and the argument as a
list of structs, i.e.:

  $ pahole skb_ext,list_head
  struct list_head {
  	struct list_head *         next;                 /*     0     8 */
  	struct list_head *         prev;                 /*     8     8 */

  	/* size: 16, cachelines: 1, members: 2 */
  	/* last cacheline: 16 bytes */
  };
  struct skb_ext {
  	refcount_t                 refcnt;               /*     0     4 */
  	u8                         offset[3];            /*     4     3 */
  	u8                         chunks;               /*     7     1 */
  	char                       data[];               /*     8     0 */

  	/* size: 8, cachelines: 1, members: 4 */
  	/* last cacheline: 8 bytes */
  };
  $ pahole hlist_node
  struct hlist_node {
  	struct hlist_node *        next;                 /*     0     8 */
  	struct hlist_node * *      pprev;                /*     8     8 */

  	/* size: 16, cachelines: 1, members: 2 */
  	/* last cacheline: 16 bytes */
  };
  $

Of course -C continues to work:

  $ pahole -C inode | tail
  	__u32                      i_fsnotify_mask;      /*   556     4 */
  	struct fsnotify_mark_connector * i_fsnotify_marks; /*   560     8 */
  	struct fscrypt_info *      i_crypt_info;         /*   568     8 */
  	/* --- cacheline 9 boundary (576 bytes) --- */
  	struct fsverity_info *     i_verity_info;        /*   576     8 */
  	void *                     i_private;            /*   584     8 */

  	/* size: 592, cachelines: 10, members: 53 */
  	/* last cacheline: 16 bytes */
  };
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-14 14:04:09 -03:00
Arnaldo Carvalho de Melo 1944de0c93 pahole: Use function__for_each_parameter()
To take into account BTF in a more abstracted way.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-14 14:01:30 -03:00
Arnaldo Carvalho de Melo 66e640508e dwarves: Make function__for_each_parameter receive 'cu' arg
Needed to find the right 'struct ftype' to iterate function arguments
on. This is due to how BTF works with this and how we implemented it, at
some point this can get improved to avoid the need for checking if it is
BTF, doing it in a more format abstracted way, but for now, abstract
this away in the for_each_parameter helpers.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-09 14:16:52 -03:00
Arnaldo Carvalho de Melo 252b0fcc91 pahole: Fix -m/--nr_methods - Number of functions operating on a type pointer
We had to use the same hack as in pfunct, as implemented in ccf3eebfcd
("btf_loader: Add support for BTF_KIND_FUNC"), will hide that 'struct
ftype' (aka function prototype) indirection behind the parameter
iterator (function__for_each_parameter).

For now, here is the top 10 Linux kernel data structures in terms of
number of functions receiving as one of its parameters a pointer to it,
using /sys/kernel/btf/vmlinux to look at all the vmlinux types and
functions (the ones visible in kallsyms, but with the parameters and its
types):

  $ pahole -m | sort -k2 -nr | head
  device	955
  sock		568
  sk_buff	541
  task_struct	437
  inode		421
  pci_dev	390
  page		351
  net_device	347
  file		315
  net		312
  $
  $ pahole --help |& grep -- -m
    -m, --nr_methods           show number of methods
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-08 11:52:37 -03:00
Arnaldo Carvalho de Melo 202c8d5f5b pahole: Do not require a class name to operate without a file name
Since we default to operating on the running kernel data structures, we
should make the default to, with no options passed, to pretty print all
the running kernel data structures, or do what was asked in terms of
number of members, size of structs, etc, i.e.:

  [root@quaco ~]# pahole --help |& head
  Usage: pahole [OPTION...] FILE

    -a, --anon_include         include anonymous classes
    -A, --nested_anon_include  include nested (inside other structs) anonymous
                               classes
    -B, --bit_holes=NR_HOLES   Show only structs at least NR_HOLES bit holes
    -c, --cacheline_size=SIZE  set cacheline size to SIZE
        --classes_as_structs   Use 'struct' when printing classes
    -C, --class_name=CLASS_NAME   Show just this class
    -d, --recursive            recursive mode, affects several other flags
  [root@quaco ~]#

Continues working as before, but if you do:

  pahole

It will work just as if you did:

  pahole vmlinux

and that vmlinux file is the running kernel vmlinux.

And since the default now is to read BTF info, then it will do all its
operations on /sys/kernel/btf/vmlinux, when present, i.e. want to know
what are the fattest data structures in the running kernel:

  [root@quaco ~]# pahole -s | sort -k2 -nr | head
  cmp_data	290904	1
  dec_data	274520	1
  cpu_entry_area	217088	0
  pglist_data	172928	4
  saved_cmdlines_buffer	131104	1
  debug_store_buffers	131072	0
  hid_parser	110848	1
  hid_local	110608	0
  zonelist	81936	0
  e820_table	64004	0
  [root@quaco ~]#

How many data structures in the running kernel vmlinux area embbed
'struct list_head'?

  [root@quaco ~]# pahole -i list_head | wc -l
  260
  [root@quaco ~]#

Lets see some of those?

  [root@quaco ~]# pahole -C fsnotify_event
  struct fsnotify_event {
  	struct list_head           list;                 /*     0    16 */
  	struct inode *             inode;                /*    16     8 */

  	/* size: 24, cachelines: 1, members: 2 */
  	/* last cacheline: 24 bytes */
  };
  [root@quaco ~]# pahole -C audit_chunk
  struct audit_chunk {
  	struct list_head           hash;                 /*     0    16 */
  	long unsigned int          key;                  /*    16     8 */
  	struct fsnotify_mark *     mark;                 /*    24     8 */
  	struct list_head           trees;                /*    32    16 */
  	int                        count;                /*    48     4 */

  	/* XXX 4 bytes hole, try to pack */

  	atomic_long_t              refs;                 /*    56     8 */
  	/* --- cacheline 1 boundary (64 bytes) --- */
  	struct callback_head       head;                 /*    64    16 */
  	struct node                owners[];             /*    80     0 */

  	/* size: 80, cachelines: 2, members: 8 */
  	/* sum members: 76, holes: 1, sum holes: 4 */
  	/* last cacheline: 16 bytes */
  };
  [root@quaco ~]#

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-06 13:53:37 -03:00
Arnaldo Carvalho de Melo 617f5ac2e6 dwarves: Move BTF loader ahead of the CTF one
When we call the tools without specifying a file format, all the
available format loaders are called, in sequence, till we find the
relevant information, now that we support raw BTF we better move it in
front of the CTF one, as it is way more common in the Linux community.

With this we will not see this warning anymore:

  $ pahole -C list_head  /sys/kernel/btf/vmlinux
  ctf__new: cannot get elf header.
  struct list_head {
  	struct list_head *         next;                 /*     0     8 */
  	struct list_head *         prev;                 /*     8     8 */

  	/* size: 16, cachelines: 1, members: 2 */
  	/* last cacheline: 16 bytes */
  };
  $

That warning has to go, so that other formats, if present after the CTF
one, can be tried.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-06 13:09:27 -03:00
Arnaldo Carvalho de Melo cdd5e1399b btf loader: Support raw BTF as available in /sys/kernel/btf/vmlinux
Be it automatically when no -F option is passed and
/sys/kernel/btf/vmlinux is available, or when /sys/kernel/btf/vmlinux is
passed as the filename to the tool, i.e.:

  $ pahole -C list_head
  struct list_head {
  	struct list_head *         next;                 /*     0     8 */
  	struct list_head *         prev;                 /*     8     8 */

  	/* size: 16, cachelines: 1, members: 2 */
  	/* last cacheline: 16 bytes */
  };
  $ strace -e openat pahole -C list_head |& grep /sys/kernel/btf/
  openat(AT_FDCWD, "/sys/kernel/btf/vmlinux", O_RDONLY) = 3
  $
  $ pahole -C list_head /sys/kernel/btf/vmlinux
  struct list_head {
  	struct list_head *         next;                 /*     0     8 */
  	struct list_head *         prev;                 /*     8     8 */

  	/* size: 16, cachelines: 1, members: 2 */
  	/* last cacheline: 16 bytes */
  };
  $

If one wants to grab the matching vmlinux to use its DWARF info instead,
which is useful to compare the results with what we have from BTF, for
instance, its just a matter of using '-F dwarf'.

This in turn shows something that at first came as a surprise, but then
has a simple explanation:

For very common data structures, that will probably appear in all of the
DWARF CUs (Compilation Units), like 'struct list_head', using '-F dwarf'
is faster:

  [acme@quaco pahole]$ perf stat -e cycles pahole -F btf -C list_head > /dev/null

   Performance counter stats for 'pahole -F btf -C list_head':

          45,722,518      cycles:u

         0.023717300 seconds time elapsed

         0.016474000 seconds user
         0.007212000 seconds sys

  [acme@quaco pahole]$ perf stat -e cycles pahole -F dwarf -C list_head > /dev/null

   Performance counter stats for 'pahole -F dwarf -C list_head':

          14,170,321      cycles:u

         0.006668904 seconds time elapsed

         0.005562000 seconds user
         0.001109000 seconds sys

  [acme@quaco pahole]$

But for something that is more specific to a subsystem, the DWARF loader
will have to process way more stuff till it gets to that struct:

  $ perf stat -e cycles pahole -F dwarf -C tcp_sock > /dev/null

   Performance counter stats for 'pahole -F dwarf -C tcp_sock':

      31,579,795,238      cycles:u

         8.332272930 seconds time elapsed

         8.032124000 seconds user
         0.286537000 seconds sys

  $

While using the BTF loader the time should be constant, as it loads
everything from /sys/kernel/btf/vmlinux:

  $ perf stat -e cycles pahole -F btf -C tcp_sock > /dev/null

   Performance counter stats for 'pahole -F btf -C tcp_sock':

          48,823,488      cycles:u

         0.024102760 seconds time elapsed

         0.012035000 seconds user
         0.012046000 seconds sys

  $

Above I used '-F btf' just to show that it can be used, but its not
really needed, i.e. those are equivalent:

  $ strace -e openat pahole -F btf -C list_head |& grep /sys/kernel/btf/vmlinux
  openat(AT_FDCWD, "/sys/kernel/btf/vmlinux", O_RDONLY) = 3
  $ strace -e openat pahole -C list_head |& grep /sys/kernel/btf/vmlinux
  openat(AT_FDCWD, "/sys/kernel/btf/vmlinux", O_RDONLY) = 3
  $

The btf_raw__load() function that ends up being grafted into the
preexisting btf_elf routines was based on libbpf's btf_load_raw().

Acked-by: Alexei Starovoitov <ast@fb.com>
Cc: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-06 13:09:16 -03:00
Arnaldo Carvalho de Melo 1c1af2cd19 dwarves: Prep v1.16
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-12-16 11:43:53 -03:00
Alexei Starovoitov 69df73444c dwarves: Add -O2 to CFLAGS
Using the defaults, which uses no -O flags:

  [acme@quaco pahole]$ grep CMAKE_C_FLAGS_RELEASE CMakeLists.txt
  set(CMAKE_C_FLAGS_RELEASE "-Wall")
  [acme@quaco pahole]$ perf stat -r5 pahole -J vmlinux

   Performance counter stats for 'pahole -J vmlinux' (5 runs):

           18,516.09 msec task-clock:u              #    1.000 CPUs utilized            ( +-  0.55% )
                   0      context-switches:u        #    0.000 K/sec
                   0      cpu-migrations:u          #    0.000 K/sec
             548,753      page-faults:u             #    0.030 M/sec                    ( +-  0.00% )
      68,498,897,915      cycles:u                  #    3.699 GHz                      ( +-  0.05% )
     123,209,200,210      instructions:u            #    1.80  insn per cycle           ( +-  0.00% )
      25,484,050,414      branches:u                # 1376.319 M/sec                    ( +-  0.00% )
         366,334,745      branch-misses:u           #    1.44% of all branches          ( +-  0.03% )

              18.518 +- 0.102 seconds time elapsed  ( +-  0.55% )

  [acme@quaco pahole]$

With this patch, using -O2:

  [acme@quaco pahole]$ grep CMAKE_C_FLAGS_RELEASE CMakeLists.txt
  set(CMAKE_C_FLAGS_RELEASE "-Wall -O2")
  [acme@quaco pahole]$ perf stat -r5 pahole -J vmlinux

   Performance counter stats for 'pahole -J vmlinux' (5 runs):

           12,645.96 msec task-clock:u              #    1.000 CPUs utilized            ( +-  0.61% )
                   0      context-switches:u        #    0.000 K/sec
                   0      cpu-migrations:u          #    0.000 K/sec
             548,744      page-faults:u             #    0.043 M/sec                    ( +-  0.00% )
      45,359,248,873      cycles:u                  #    3.587 GHz                      ( +-  0.03% )
      84,051,005,257      instructions:u            #    1.85  insn per cycle           ( +-  0.00% )
      19,755,005,738      branches:u                # 1562.159 M/sec                    ( +-  0.00% )
         365,276,883      branch-misses:u           #    1.85% of all branches          ( +-  0.12% )

             12.6471 +- 0.0771 seconds time elapsed  ( +-  0.61% )

  [acme@quaco pahole]$

Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-12-16 11:19:47 -03:00
Arnaldo Carvalho de Melo 6d11dd157f elfcreator: Address initialization warning emitted by 'gcc -O6'
Addresses this warning:

  [ 67%] Building C object CMakeFiles/scncopy.dir/elfcreator.c.o
  /home/acme/git/pahole/elfcreator.c: In function ‘rel_dyn_fixup_fn’:
  /home/acme/git/pahole/elfcreator.c:229:3: error: ‘idx’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
    229 |   gelf_update_dyn(ctor->dyndata, idx, dyn);
        |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /home/acme/git/pahole/elfcreator.c: In function ‘rela_dyn_fixup_fn’:
  /home/acme/git/pahole/elfcreator.c:208:3: error: ‘idx’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
    208 |   gelf_update_dyn(ctor->dyndata, idx, dyn);
        |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /home/acme/git/pahole/elfcreator.c: In function ‘elfcreator_end’:
  /home/acme/git/pahole/elfcreator.c:192:3: error: ‘idx’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
    192 |   gelf_update_dyn(ctor->dyndata, idx, dyn);
        |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /home/acme/git/pahole/elfcreator.c:186:9: note: ‘idx’ was declared here
    186 |  size_t idx;
        |         ^~~
  cc1: all warnings being treated as errors

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-12-16 11:19:47 -03:00
Arnaldo Carvalho de Melo 1bc63a4cff fprintf: Fixup truncation possibility pointed out by gcc -O2
Addresses this warning:

  [ 26%] Building C object CMakeFiles/dwarves.dir/dwarves_fprintf.c.o
  /home/acme/git/pahole/dwarves_fprintf.c: In function ‘type__fprintf’:
  /home/acme/git/pahole/dwarves_fprintf.c:709:47: error: ‘%s’ directive output may be truncated writing up to 257 bytes into a region of size 256 [-Werror=format-truncation=]
    709 |     snprintf(namebfptr, sizeof(namebfptr), "* %s", name);
        |                                               ^~
  /home/acme/git/pahole/dwarves_fprintf.c:709:5: note: ‘snprintf’ output between 3 and 260 bytes into a destination of size 258
    709 |     snprintf(namebfptr, sizeof(namebfptr), "* %s", name);
        |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cc1: all warnings being treated as errors

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-12-16 11:19:47 -03:00
Arnaldo Carvalho de Melo 5c590fc29d ptr_table: Zero out new id ranges
Since we iterate over these ptr_tables entry by entry, we better zero
out the new ranges, i.e. whatever is after the previous allocated space
up to the new one, returned by realloc.

Fixes a bug found using pahole -F btf on a vmlinux file, now btfdiff on
this same file comes clean, i.e. the output from its BTF tags is the
same as with its DWARF ones, for the features present in both type
information formats.

Tested-by: Alexei Starovoitov <ast@fb.com>
Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-12-16 11:19:07 -03:00
Arnaldo Carvalho de Melo 644466dce7 fprintf: Remove extraneous sizeof operator
That was affecting --suppress_aligned_attribute, detected using the
'btfdiff' utility, that uses pahole with DWARF and BTF and compares
their outputs, and since we don't have this in BTF, we use
--suppress_aligned_attribute with '-F dwarf'.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-12-13 11:35:13 -03:00
Arnaldo Carvalho de Melo a59459bb80 fprintf: Account inline type __aligned__ member types for spacing
Fixing things like that anonymous union offset/size comment
misalignment:

          union {
                  refcount_t         rcu_users;            /*  2568     4 */
                  struct callback_head rcu __attribute__((__aligned__(8))); /*  2568    16 */
  -       } __attribute__((__aligned__(8)));                                               /*  2568    16 */
  +       } __attribute__((__aligned__(8)));               /*  2568    16 */
          struct pipe_inode_info *   splice_pipe;          /*  2584     8 */
          struct page_frag           task_frag;            /*  2592    16 */
          struct task_delay_info *   delays;               /*  2608     8 */

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-11-19 12:23:00 -03:00
Arnaldo Carvalho de Melo 56547f133a fprintf: Fix alignment of class members that are structs/enums/unions
E.g. look at that 'completion' member in this struct:

   struct cpu_stop_done {
          atomic_t                   nr_todo;              /*     0     4 */
          int                        ret;                  /*     4     4 */
  -       struct completion  completion;                   /*     8    32 */
  +       struct completion          completion;           /*     8    32 */

          /* size: 40, cachelines: 1, members: 3 */
          /* last cacheline: 40 bytes */

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-11-19 11:48:36 -03:00
Gareth Lloyd be37b64aef dwarves: Ignore static members for alignment
It was possible to have an infinite loop trying to determine the
alignment of a type that had a static data member of its own type.

Example code illustrating the problem.
struct X { static X thing; };

Committer testing:

Before:

  $ pwd
  /home/acme/git/pahole/examples/gareth
  $ cat static_member.cpp
  struct X { static X thing; };

  static struct X f;
  $ g++ -g -c static_member.cpp -o static_member.o
  $ pahole static_member.o
  Segmentation fault (core dumped)
  $

After:

  $ pahole static_member.o
  struct X {
  	static struct X           thing;                 /*     0     0 */

  	/* XXX last struct has 1 byte of padding */

  	/* size: 1, cachelines: 0, members: 0, static members: 1 */
  	/* padding: 1 */
  	/* paddings: 1, sum paddings: 1 */
  	/* last cacheline: 1 bytes */
  };
  $

Signed-off-by: Gareth Lloyd <gareth.lloyd@uk.ibm.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-11-12 17:47:50 -03:00
Jiri Olsa cca018e495 SPEC: Add dwarves dependency on libdwarves1
while adding the RHEL package one of the checks failed
saying that there's no actual version dependency between
dwarves nad libdwarves1:

  Subpackage dwarves on aarch64 x86_64 ppc64le s390x consumes libraries libdwarves.so.1()(64bit) libdwarves_emit.so.1()(64bit) libdwarves_reorganize.so.1()(64bit) from subpackage libdwarves1 but does not have explicit package version requirement.
  Please add Requires: libdwarves1 = %{version}-%{release} to dwarves in the specfile to avoid the need to test interoperability between the various combinations of old and new subpackages.

It's also not present in fedora and I think that's what we want,
because it's also present for -devel pacakge.. please consider
patch below for fedora package.

  koji: https://koji.fedoraproject.org/koji/taskinfo?taskID=38777298

  [jolsa@krava trash]$ rpm -qp --requires dwarves-1.15-4.fc32.x86_64.rpm  | grep libdwarves1
  libdwarves1 = 1.15-4.fc32

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Martin Cermak <mcermak@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-11-05 12:20:41 -03:00
Arnaldo Carvalho de Melo ccf3eebfcd btf_loader: Add support for BTF_KIND_FUNC
Some changes to the fprintf routines were needed, as BTF has as the
function type just a BTF_KIND_FUNC_PROTO, while DWARF has as the type
for a function its return value type. With a function->btf flag this was
overcome and all the other goodies in pfunct are present, for instance:

  $ pahole -JV examples/tcp.o | grep -w FUNC | head
  [4068] FUNC tcp_init type_id=4067
  [4070] FUNC tcp_abort type_id=4069
  [4072] FUNC tcp_done type_id=4071
  [4074] FUNC tcp_md5_hash_key type_id=4073
  [4076] FUNC tcp_md5_hash_skb_data type_id=4075
  [4078] FUNC tcp_get_md5sig_pool type_id=4077
  [4080] FUNC tcp_alloc_md5sig_pool type_id=4079
  [4082] FUNC compat_tcp_getsockopt type_id=4081
  [4084] FUNC tcp_getsockopt type_id=4083
  [4086] FUNC tcp_get_timestamping_opt_stats type_id=4085
  $

  $ pfunct -F btf examples/tcp.o  | head
  memset
  memcpy
  tcp_enter_memory_pressure
  tcp_leave_memory_pressure
  tcp_init_sock
  tcp_init_transfer
  tcp_poll
  tcp_ioctl
  tcp_splice_read
  sk_stream_alloc_skb
  $

  $ pfunct --prototype -F btf examples/tcp.o | head
  void * memset(void * p, int c, __kernel_size_t size);
  void * memcpy(void * p, const void  * q, __kernel_size_t size);
  void tcp_enter_memory_pressure(struct sock * sk);
  void tcp_leave_memory_pressure(struct sock * sk);
  void tcp_init_sock(struct sock * sk);
  void tcp_init_transfer(struct sock * sk, int bpf_op);
  __poll_t tcp_poll(struct file * file, struct socket * sock, poll_table * wait);
  int tcp_ioctl(struct sock * sk, int cmd, long unsigned int arg);
  ssize_t tcp_splice_read(struct socket * sock, loff_t * ppos, struct pipe_inode_info * pipe, size_t len, unsigned int flags);
  struct sk_buff * sk_stream_alloc_skb(struct sock * sk, int size, gfp_t gfp, bool force_schedule);
  $

Now to ask just for the 'struct sock' 'methods', i.e. functions that
have as one of its arguments a pointer to the given 'class' name:

  $ pfunct --class sock -F btf examples/tcp.o | head
  tcp_abort
  tcp_done
  compat_tcp_getsockopt
  tcp_getsockopt
  tcp_get_info
  compat_tcp_setsockopt
  tcp_setsockopt
  tcp_disconnect
  tcp_write_queue_purge
  tcp_close
  $

Then ask for the prototypes, which requires -V, should have that fixed:

  $ pfunct -V --prototypes --class sock -F btf examples/tcp.o | head
  int tcp_abort(struct sock * sk, int err);
  void tcp_done(struct sock * sk);
  int compat_tcp_getsockopt(struct sock * sk, int level, int optname, char * optval, int * optlen);
  int tcp_getsockopt(struct sock * sk, int level, int optname, char * optval, int * optlen);
  void tcp_get_info(struct sock * sk, struct tcp_info * info);
  int compat_tcp_setsockopt(struct sock * sk, int level, int optname, char * optval, unsigned int optlen);
  int tcp_setsockopt(struct sock * sk, int level, int optname, char * optval, unsigned int optlen);
  int tcp_disconnect(struct sock * sk, int flags);
  void tcp_write_queue_purge(struct sock * sk);
  void tcp_close(struct sock * sk, long int timeout);
  $

Don't like prototypes with parm names, got you covered:

  $ pfunct --no_parm_names -V --prototypes --class sock -F btf examples/tcp.o | head
  int tcp_abort(struct sock *, int);
  void tcp_done(struct sock *);
  int compat_tcp_getsockopt(struct sock *, int, int, char *, int *);
  int tcp_getsockopt(struct sock *, int, int, char *, int *);
  void tcp_get_info(struct sock *, struct tcp_info *);
  int compat_tcp_setsockopt(struct sock *, int, int, char *, unsigned int);
  int tcp_setsockopt(struct sock *, int, int, char *, unsigned int);
  int tcp_disconnect(struct sock *, int);
  void tcp_write_queue_purge(struct sock *);
  void tcp_close(struct sock *, long int);
  $

Don't like long options and want just one function?

  $ pfunct -f tcp_setsockopt -F btf examples/tcp.o
  int tcp_setsockopt(struct sock * sk, int level, int optname, char * optval, unsigned int optlen);
  $

Want to generate compileable code for all of those functions, full with
the necessary types, etc?

  $ pfunct -F btf --compile examples/tcp.o  > a.c
  $ gcc -c -o a.o a.c
  $ pfunct -F dwarf --prototypes --class sock a.o | head
  pfunct: a.o: No debugging information found
  $ gcc -g -c -o a.o a.c
  $ pfunct -V -F dwarf --prototypes --class sock a.o | head
  void tcp_enter_memory_pressure(struct sock * sk);
  void tcp_leave_memory_pressure(struct sock * sk);
  void tcp_init_sock(struct sock * sk);
  void tcp_init_transfer(struct sock * sk, int bpf_op);
  int tcp_ioctl(struct sock * sk, int cmd, long unsigned int arg);
  struct sk_buff * sk_stream_alloc_skb(struct sock * sk, int size, gfp_t gfp, bool force_schedule);
  ssize_t do_tcp_sendpages(struct sock * sk, struct page * page, int offset, size_t size, int flags);
  int tcp_sendpage_locked(struct sock * sk, struct page * page, int offset, size_t size, int flags);
  int tcp_sendpage(struct sock * sk, struct page * page, int offset, size_t size, int flags);
  int tcp_sendmsg_locked(struct sock * sk, struct msghdr * msg, size_t size);
  $

Now lets go full circle and encode BTF for this a.o generated from
source code generated from the original BTF info in that examples/tcp.o
file:

  $ pahole -JV a.o | tail
  [465] FUNC_PROTO (anon) return=35 args=(392 hp, 393 skb, 5 header_len)
  [466] FUNC tcp_md5_hash_skb_data type_id=465
  [467] FUNC_PROTO (anon) return=35 args=(392 hp, 394 key)
  [468] FUNC tcp_md5_hash_key type_id=467
  [469] FUNC_PROTO (anon) return=0 args=(49 sk)
  [470] FUNC tcp_done type_id=469
  [471] FUNC_PROTO (anon) return=35 args=(49 sk, 35 err)
  [472] FUNC tcp_abort type_id=471
  [473] FUNC_PROTO (anon) return=0 args=(void)
  [474] FUNC tcp_init type_id=473
  $

  $ pfunct -F btf -V --prototypes --class=sock a.o | head
  void tcp_enter_memory_pressure(struct sock * sk);
  void tcp_leave_memory_pressure(struct sock * sk);
  void tcp_init_sock(struct sock * sk);
  void tcp_init_transfer(struct sock * sk, int bpf_op);
  int tcp_ioctl(struct sock * sk, int cmd, long unsigned int arg);
  struct sk_buff * sk_stream_alloc_skb(struct sock * sk, int size, gfp_t gfp, bool force_schedule);
  ssize_t do_tcp_sendpages(struct sock * sk, struct page * page, int offset, size_t size, int flags);
  int tcp_sendpage_locked(struct sock * sk, struct page * page, int offset, size_t size, int flags);
  int tcp_sendpage(struct sock * sk, struct page * page, int offset, size_t size, int flags);
  int tcp_sendmsg_locked(struct sock * sk, struct msghdr * msg, size_t size);
  $

Curious about the code generated by 'pfunct -F btf --compile examples/tcp.o?

  http://vger.kernel.org/~acme/pahole/pfunct-F-BTF--compile-examples-tcp.o.txt

Cc: Alexei Starovoitov <ast@fb.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Andrii Nakryiko <andriin@fb.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Yonghong Song <yhs@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-11-05 12:04:23 -03:00
Arnaldo Carvalho de Melo f95fd85f7b pfunct: type->type == 0 is void, fix --compile for that
We were using the fall back for that, i.e. 'return 0;' was being emitted
for a function returning void, noticed with using BTF as the format.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-11-05 12:04:17 -03:00
Arnaldo Carvalho de Melo 3e8f09e304 pdwtags: Print DW_TAG_subroutine_type as well
So that we can see at least via pdwtags those tags, be it from DWARF of
BTF.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-11-05 10:16:25 -03:00
Andrii Nakryiko 3c5f2a224a btf_encoder: Preserve and encode exported functions as BTF_KIND_FUNC
Add encoding of DWARF's DW_TAG_subprogram_type into BTF's BTF_KIND_FUNC
(plus corresponding BTF_KIND_FUNC_PROTO). Only exported functions are
converted for now. This allows to capture all the exported kernel
functions, same subset that's exposed through /proc/kallsyms.

Committer testing:

Before:

  $ readelf -SW vmlinux  | grep BTF
    [78] .BTF              PROGBITS        0000000000000000 26a27da9 1e5543 00      0   0  1
  $

After:

  $ pahole -J vmlinux
  $ readelf -SW vmlinux  | grep BTF
    [78] .BTF              PROGBITS        0000000000000000 26a27da9 2d5f47 00      0   0  1
  $

  >>> 0x2d5f47 - 0x1e5543
  985604

The kernel has a lot of functions! :-)

  $ pahole -VJ vmlinux > /tmp/pahole-btf-encoding-verbose-output.txt

  $ grep -w FUNC /tmp/pahole-btf-encoding-verbose-output.txt | wc -l
  22871
  [acme@quaco pahole]$ grep -w FUNC /tmp/pahole-btf-encoding-verbose-output.txt | tail
  [4511543] FUNC copy_from_user_nmi type_id=4511542
  [4512934] FUNC memcpy_page_flushcache type_id=4512933
  [4512936] FUNC __memcpy_flushcache type_id=4512935
  [4512938] FUNC __copy_user_flushcache type_id=4512937
  [4512940] FUNC arch_wb_cache_pmem type_id=4512939
  [4512942] FUNC mcsafe_handle_tail type_id=4512941
  [4512944] FUNC copy_user_handle_tail type_id=4512943
  [4512946] FUNC clear_user type_id=4512945
  [4512948] FUNC __clear_user type_id=4512947
  [4512950] FUNC memcpy type_id=4512949
  $ grep -w FUNC_PROTO /tmp/pahole-btf-encoding-verbose-output.txt | tail
  [4512902] FUNC_PROTO (anon) return=4511725 args=(4512097 (anon), 4511544 (anon))
  [4512933] FUNC_PROTO (anon) return=0 args=(4511598 to, 4511725 page, 4511610 offset, 4511610 len)
  [4512935] FUNC_PROTO (anon) return=0 args=(4511638 _dst, 4511759 _src, 4511610 size)
  [4512937] FUNC_PROTO (anon) return=4511585 args=(4511638 dst, 4511759 src, 4511552 size)
  [4512939] FUNC_PROTO (anon) return=0 args=(4511638 addr, 4511610 size)
  [4512941] FUNC_PROTO (anon) return=4511544 args=(4511598 to, 4511598 from, 4511552 len)
  [4512943] FUNC_PROTO (anon) return=4511544 args=(4511598 to, 4511598 from, 4511552 len)
  [4512945] FUNC_PROTO (anon) return=4511544 args=(4511638 to, 4511544 n)
  [4512947] FUNC_PROTO (anon) return=4511544 args=(4511638 addr, 4511544 size)
  [4512949] FUNC_PROTO (anon) return=4511638 args=(4511638 p, 4511759 q, 4511591 size)
  $ grep -w FUNC_PROTO /tmp/pahole-btf-encoding-verbose-output.txt |grep 4511542
  [4511542] FUNC_PROTO (anon) return=4510159 args=(4510254 to, 4510374 from, 4510159 n)
  $

With a little change to pdwtags to see DW_TAG_subroutine_type, which is
what BTF's KIND_FUNC_PROTO maps to, we see some of those last
prototypes:

[acme@quaco pahole]$ pdwtags -F btf vmlinux  | grep '()(' | tail
void ()(struct insn * insn); /* size: 45404744 */
int ()(struct insn * insn); /* size: 4 */
void ()(struct insn * insn, const void  * kaddr, int buf_len, int x86_64); /* size: 45405032 */
long unsigned int ()(const char  * purpose); /* size: 8 */
void ()(char * to, struct page * page, size_t offset, size_t len); /* size: 45405864 */
void ()(void * _dst, const void  * _src, size_t size); /* size: 45406200 */
long int ()(void * dst, const void  * src, unsigned int size); /* size: 8 */
long unsigned int ()(char * to, char * from, unsigned int len); /* size: 8 */
long unsigned int ()(void * to, long unsigned int n); /* size: 8 */
long unsigned int ()(void * addr, long unsigned int size); /* size: 8 */
[acme@quaco pahole]$

I.e.:

  [4512941] FUNC_PROTO (anon) return=4511544 args=(4511598 to, 4511598 from, 4511552 len)

gets decoded by pdwtags as:

  long unsigned int ()(char * to, char * from, unsigned int len); /* size: 8 */

  $ grep '\[\(4511544\|4511598\|4511550\|4511552\)\]' /tmp/pahole-btf-encoding-verbose-output.txt
  [4511544] INT long unsigned int size=8 bit_offset=0 nr_bits=64 encoding=(none)
  [4511550] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none)
  [4511552] INT unsigned int size=4 bit_offset=0 nr_bits=32 encoding=(none)
  [4511598] PTR (anon) type_id=4511550
  $

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-11-05 09:27:58 -03:00
Arnaldo Carvalho de Melo 910e060b5c btf_loader: Skip BTF_KIND_DATASEC entries
Just skip them, we have no use for them so far, skipping them will allow
us to process the other kinds we have use for.

Cc: Andrii Nakryiko <andriin@fb.com>
Cc: Daniel Bristot de Oliveira <bristot@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Yonghong Song <yhs@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-10-24 21:02:33 -03:00
Arnaldo Carvalho de Melo 96235a74a3 btf_loader: Replace if/else series with a proper switch {}
A switch is the right thing here, use it.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-10-24 20:56:31 -03:00