For the threaded code we want to access strings in tags at the same time
that the string table may grow in another thread making the previous
pointer invalid, so, to avoid excessive locking, use plain strings.
The way the tools work will either consume the just produced CU straight
away or keep just one copy of each data structure when we keep all CUs
in memory, so lets try stopping using strings_t for strings.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
For the threaded code we want to access strings in tags at the same time
that the string table may grow in another thread making the previous
pointer invalid, so, to avoid excessive locking, use plain strings.
The way the tools work will either consume the just produced CU straight
away or keep just one copy of each data structure when we keep all CUs
in memory, so lets try stopping using strings_t for strings.
For the enumerator->name case we get the bonus of removing the last user
of dwarves__active_loader in the btf_encoder class.
This covers unions, enums, structs and classes.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
For the threaded code we want to access strings in tags at the same time
that the string table may grow in another thread making the previous
pointer invalid, so, to avoid excessive locking, use plain strings.
The way the tools work will either consume the just produced CU straight
away or keep just one copy of each data structure when we keep all CUs
in memory, so lets try stopping using strings_t for strings.
For the namespace->name case we get the bonus of removing another
user of dwarves__active_loader.
This covers unions, enums, structs and classes.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
For the threaded code we want to access strings in tags at the same time
that the string table may grow in another thread making the previous
pointer invalid, so, to avoid excessive locking, use plain strings.
The way the tools work will either consume the just produced CU straight
away or keep just one copy of each data structure when we keep all CUs
in memory, so lets try stopping using strings_t for strings.
For the class_member->name case we get the bonus of removing another
user of dwarves__active_loader.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
For the threaded code we want to access strings in tags at the same time
that the string table may grow in another thread making the previous
pointer invalid, so, to avoid excessive locking, use plain strings.
The way the tools work will either consume the just produced CU straight
away or keep just one copy of each data structure when we keep all CUs
in memory, so lets try stopping using strings_t for strings.
For the parameter->name case we get the bonus of removing a user of
dwarves__active_loader.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
For the threaded code we want to access strings in tags at the same time
that the string table may grow in another thread making the previous
pointer invalid, so, to avoid excessive locking, use plain strings.
The way the tools work will either consume the just produced CU straight
away or keep just one copy of each data structure when we keep all CUs
in memory, so lets try stopping using strings_t for strings.
For the base_type->name case we get the bonus of removing some more
functions related base types and a user of dwarves__active_loader.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
For the threaded code we want to access strings in tags at the same time
that the string table may grow in another thread making the previous
pointer invalid, so, to avoid excessive locking, use plain strings.
The way the tools work will either consume the just produced CU straight
away or keep just one copy of each data structure when we keep all CUs
in memory, so lets try stopping using strings_t for strings.
For the function->name case we get the bonus of removing the need of a
debug_fmt_ops->function() callback receiving the 'cu', just access the
string directly.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Add a new CMake option, LIBBPF_EMBEDDED, to switch between the embedded
version and the system version (searched via pkg-config) of libbpf. Set
the embedded version as the default.
Committer testing:
The default build works as before:
⬢[acme@toolbox pahole]$ rm -rf build ; mkdir build ; cd build ; cmake -DCMAKE_BUILD_TYPE=Release .. ; cd ..
-- The C compiler identification is GNU 11.1.1
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Checking availability of DWARF and ELF development libraries
-- Looking for dwfl_module_build_id in elf
-- Looking for dwfl_module_build_id in elf - found
-- Found dwarf.h header: /usr/include
-- Found elfutils/libdw.h header: /usr/include
-- Found libdw library: /usr/lib64/libdw.so
-- Found libelf library: /usr/lib64/libelf.so
-- Checking availability of DWARF and ELF development libraries - done
-- Found ZLIB: /usr/lib64/libz.so (found version "1.2.11")
-- Submodule update
-- Submodule update - done
-- Performing Test HAVE_REALLOCARRAY_SUPPORT
-- Performing Test HAVE_REALLOCARRAY_SUPPORT - Success
-- Configuring done
-- Generating done
-- Build files have been written to: /var/home/acme/git/pahole/build
⬢[acme@toolbox pahole]$ make -j28 -C build
make: Entering directory '/var/home/acme/git/pahole/build'
make[1]: Entering directory '/var/home/acme/git/pahole/build'
make[2]: Entering directory '/var/home/acme/git/pahole/build'
Scanning dependencies of target bpf
make[2]: Leaving directory '/var/home/acme/git/pahole/build'
make[2]: Entering directory '/var/home/acme/git/pahole/build'
[ 5%] Building C object CMakeFiles/bpf.dir/lib/bpf/src/btf.c.o
[ 5%] Building C object CMakeFiles/bpf.dir/lib/bpf/src/bpf_prog_linfo.c.o
[ 5%] Building C object CMakeFiles/bpf.dir/lib/bpf/src/bpf.c.o
[ 7%] Building C object CMakeFiles/bpf.dir/lib/bpf/src/libbpf_errno.c.o
<SNIP>
make[2]: Leaving directory '/var/home/acme/git/pahole/build'
[ 98%] Built target ctracer
[100%] Linking C executable pahole
make[2]: Leaving directory '/var/home/acme/git/pahole/build'
[100%] Built target pahole
make[1]: Leaving directory '/var/home/acme/git/pahole/build'
make: Leaving directory '/var/home/acme/git/pahole/build'
⬢[acme@toolbox pahole]$ ldd build/pahole
linux-vdso.so.1 (0x00007ffcf4d92000)
libdwarves_reorganize.so.1 => /var/home/acme/git/pahole/build/libdwarves_reorganize.so.1 (0x00007f059c289000)
libdwarves.so.1 => /var/home/acme/git/pahole/build/libdwarves.so.1 (0x00007f059c226000)
libdw.so.1 => /lib64/libdw.so.1 (0x00007f059c186000)
libelf.so.1 => /lib64/libelf.so.1 (0x00007f059c16b000)
libz.so.1 => /lib64/libz.so.1 (0x00007f059c151000)
libc.so.6 => /lib64/libc.so.6 (0x00007f059bf82000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f059bf79000)
libzstd.so.1 => /lib64/libzstd.so.1 (0x00007f059be83000)
liblzma.so.5 => /lib64/liblzma.so.5 (0x00007f059be57000)
libbz2.so.1 => /lib64/libbz2.so.1 (0x00007f059be44000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f059be23000)
/lib64/ld-linux-x86-64.so.2 (0x00007f059c290000)
⬢[acme@toolbox pahole]$
Then, trying to use the libbpf-devel present in Fedora 34:
⬢[acme@toolbox pahole]$ rm -rf build ; mkdir build ; cd build ; cmake -DCMAKE_BUILD_TYPE=Release -DLIBBPF_EMBEDDED=Off .. ; cd ..
-- The C compiler identification is GNU 11.1.1
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "1.7.3")
-- Checking for module 'libbpf>=0.3.0'
-- Found libbpf, version 0.3.0
-- Checking availability of DWARF and ELF development libraries
-- Looking for dwfl_module_build_id in elf
-- Looking for dwfl_module_build_id in elf - found
-- Found dwarf.h header: /usr/include
-- Found elfutils/libdw.h header: /usr/include
-- Found libdw library: /usr/lib64/libdw.so
-- Found libelf library: /usr/lib64/libelf.so
-- Checking availability of DWARF and ELF development libraries - done
-- Found ZLIB: /usr/lib64/libz.so (found version "1.2.11")
-- Submodule update
-- Submodule update - done
-- Performing Test HAVE_REALLOCARRAY_SUPPORT
-- Performing Test HAVE_REALLOCARRAY_SUPPORT - Success
-- Configuring done
-- Generating done
-- Build files have been written to: /var/home/acme/git/pahole/build
⬢[acme@toolbox pahole]$ m
make: Entering directory '/var/home/acme/git/pahole/build'
make[1]: Entering directory '/var/home/acme/git/pahole/build'
make[2]: Entering directory '/var/home/acme/git/pahole/build'
Scanning dependencies of target dwarves
make[2]: Leaving directory '/var/home/acme/git/pahole/build'
make[2]: Entering directory '/var/home/acme/git/pahole/build'
[ 2%] Building C object CMakeFiles/dwarves.dir/dwarves.c.o
[ 5%] Building C object CMakeFiles/dwarves.dir/dwarves_fprintf.c.o
[ 7%] Building C object CMakeFiles/dwarves.dir/gobuffer.c.o
<SNIP>
[ 33%] Building C object CMakeFiles/dwarves.dir/rbtree.c.o
/var/home/acme/git/pahole/btf_encoder.c:84:10: error: ‘BTF_KIND_FLOAT’ undeclared here (not in a function); did you mean ‘BTF_KIND_INT’?
84 | [BTF_KIND_FLOAT] = "FLOAT",
| ^~~~~~~~~~~~~~
| BTF_KIND_INT
/var/home/acme/git/pahole/btf_encoder.c:84:10: error: array index in initializer not of integer type
/var/home/acme/git/pahole/btf_encoder.c:84:10: note: (near initialization for ‘btf_kind_str’)
/var/home/acme/git/pahole/btf_encoder.c:84:35: warning: excess elements in array initializer
84 | [BTF_KIND_FLOAT] = "FLOAT",
| ^~~~~~~
/var/home/acme/git/pahole/btf_encoder.c:84:35: note: (near initialization for ‘btf_kind_str’)
/var/home/acme/git/pahole/btf_encoder.c: In function ‘btf_encoder__add_float’:
/var/home/acme/git/pahole/btf_encoder.c:224:22: warning: implicit declaration of function ‘btf__add_float’; did you mean ‘btf__add_var’? [-Wimplicit-function-declaration]
224 | int32_t id = btf__add_float(encoder->btf, name, BITS_ROUNDUP_BYTES(bt->bit_size));
| ^~~~~~~~~~~~~~
| btf__add_var
/var/home/acme/git/pahole/btf_loader.c: In function ‘btf__load_types’:
/var/home/acme/git/pahole/btf_loader.c:455:22: error: ‘BTF_KIND_FLOAT’ undeclared (first use in this function); did you mean ‘BTF_KIND_INT’?
455 | case BTF_KIND_FLOAT:
| ^~~~~~~~~~~~~~
| BTF_KIND_INT
/var/home/acme/git/pahole/btf_loader.c:455:22: note: each undeclared identifier is reported only once for each function it appears in
make[2]: *** [CMakeFiles/dwarves.dir/build.make:173: CMakeFiles/dwarves.dir/btf_encoder.c.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[2]: *** [CMakeFiles/dwarves.dir/build.make:186: CMakeFiles/dwarves.dir/btf_loader.c.o] Error 1
make[2]: Leaving directory '/var/home/acme/git/pahole/build'
make[1]: *** [CMakeFiles/Makefile2:173: CMakeFiles/dwarves.dir/all] Error 2
make[1]: Leaving directory '/var/home/acme/git/pahole/build'
make: *** [Makefile:149: all] Error 2
make: Leaving directory '/var/home/acme/git/pahole/build'
⬢[acme@toolbox pahole]$
It doesn't build as libbpf is old and doesn't have support for
BTF_KIND_FLOAT.
Signed-off-by: Luca Boccassi <bluca@debian.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This will allow us to stop using btfe->priv and eventually btf_elf
altogether for the BTF loader.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
When loading a file, via btf__parse_split() libbtf will read the header
and have the endianness made available via the btf__endianness() API,
use it.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Error: RESOURCE_LEAK (CWE-772):
dwarves-1.21/btf_loader.c:554: alloc_fn: Storage is returned from allocation function "btf_elf__new".
dwarves-1.21/btf_loader.c:554: var_assign: Assigning: "btfe" = storage returned from "btf_elf__new(filename, NULL, base_btf)".
dwarves-1.21/btf_loader.c:561: leaked_storage: Variable "btfe" going out of scope leaks the storage it points to.
# 559| struct cu *cu = cu__new(filename, btfe->wordsize, NULL, 0, filename);
# 560| if (cu == NULL)
# 561|-> return -1;
# 562|
# 563| cu->language = LANG_C;
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Some BPF programs compiled on s390 fail to load, because s390
arch-specific linux headers contain float and double types.
Fix as follows:
- Make the DWARF loader fill base_type.float_type.
- Introduce the --btf_gen_floats command-line parameter, so that
pahole could be used to build both the older and the newer kernels.
- libbpf introduced the support for the floating-point types in commit
986962fade5, so update the libbpf submodule to that version and use
the new btf__add_float() function in order to emit the floating-point
types when not in the compatibility mode.
- Make the BTF loader recognize the new BTF kind.
Example of the resulting entry in the vmlinux BTF:
[7164] FLOAT 'double' size=8
when building with:
LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1} --btf_gen_floats
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This reverts commit 82749180b2.
Getting in the way of releasing 1.20, breaking the build of a dwarves
rpm when a libbpf package is installed in a fedora 33 system:
In file included from /home/acme/rpmbuild/BUILD/dwarves-1.20/strings.c:7:
/home/acme/rpmbuild/BUILD/dwarves-1.20/pahole_strings.h:9:10: fatal error: bpf/btf.h: No such file or directory
9 | #include <bpf/btf.h>
| ^~~~~~~~~~~
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Add a new CMake option, LIBBPF_EMBEDDED, to switch between the
embedded version and the system version (searched via pkg-config)
of libbpf. Set the embedded version as the default.
Signed-off-by: Luca Boccassi <bluca@debian.org>
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Add support for generating split BTF, in which there is a designated base
BTF, containing a base set of types, and a split BTF, which extends main BTF
with extra types, that can reference types and strings from the main BTF.
This is going to be used to generate compact BTFs for kernel modules, with
vmlinux BTF being a main BTF, which all kernel modules are based off of.
These changes rely on patch set [0] to be present in libbpf submodule.
[0] https://patchwork.kernel.org/project/netdevbpf/list/?series=377859&state=*
Committer notes:
Fixed up wrt ARGP_numeric_version and added a man page entry.
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Switch BTF loading to completely use libbpf's own struct btf and related
APIs.
BTF encoding is still happening with pahole's own code, so these two
code paths are not sharing anything now. String fetching is happening
based on whether btfe->strings were set to non-NULL pointer by
btf_encoder.
Committer testing:
$ cp ~/git/build/bpf-next-v5.9.0-rc8+/vmlinux .
$ readelf -SW vmlinux | grep BTF
[24] .BTF PROGBITS ffffffff82494ac0 1694ac0 340207 00 A 0 0 1
[25] .BTF_ids PROGBITS ffffffff827d4cc8 19d4cc8 0000a4 00 A 0 0 1
$ ./btfdiff vmlinux
$
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
pdwtags -F btf vmlinux
Was segfaulting when trying to iterate on the function main lexblock,
which was zeroed instead of INIT_LIST_HEAD'ed, fix it.
This also made pfunct misbehave when used with BTF. pahole unnafected as
it doesn't try to go thru functions in most cases.
Fixes: ccf3eebfcd ("btf_loader: Add support for BTF_KIND_FUNC")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This one just allows that to be set, i.e.:
$ pahole -C perf_event_header ~/bin/perf
struct perf_event_header {
__u32 type; /* 0 4 */
__u16 misc; /* 4 2 */
__u16 size; /* 6 2 */
/* size: 8, cachelines: 1, members: 3 */
/* last cacheline: 8 bytes */
};
$ pahole -C 'perf_event_header(sizeof=size)' --seek_bytes=0x348 --count 1 ~/bin/perf < perf.data
{
.type = 0xa,
.misc = 0x2,
.size = 0x68,
},
$
But:
$ pahole -C 'perf_event_header(sizeof=bla)' --seek_bytes=0x348 --count 1 ~/bin/perf < perf.data
pahole: the sizeof member 'bla' not found in the 'perf_event_header' type
$
And:
$ pahole -C 'perf_event_header(size=misc)' --seek_bytes=0x348 --count 1 ~/bin/perf < perf.data
pahole: invalid arg 'size' in 'perf_event_header(size=misc)' (known args: sizeof=member)
$
The next cset will implement sizeof(type) with that modifier, using the
stdin bytes to obtain the size (0x68) in the above case, and then we'll
be able to print a sequence of variable-sized records correctly.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
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>