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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>