From 20eb383fc1015199d8db64609f0a3948699daaca Mon Sep 17 00:00:00 2001 From: Jerome Marchand Date: Mon, 28 Nov 2022 11:42:31 +0100 Subject: [PATCH] Rebase to the latest version Rebase bcc to v0.25 and fix some doc and manpages issue. Resolves: rhbz#2033155 Resolves: rhbz#2074061 Resolves: rhbz#2074580 Resolves: rhbz#2074584 Resolves: rhbz#2074982 Resolves: rhbz#2074995 Resolves: rhbz#2075000 Resolves: rhbz#2075008 Resolves: rhbz#2075014 Resolves: rhbz#2075028 Resolves: rhbz#2075185 Resolves: rhbz#2075196 Resolves: rhbz#2075500 Resolves: rhbz#2075754 Resolves: rhbz#2075798 Resolves: rhbz#2075828 Resolves: rhbz#2075832 Resolves: rhbz#2075877 Resolves: rhbz#2077863 Resolves: rhbz#2078065 Resolves: rhbz#2078067 Resolves: rhbz#2078432 Resolves: rhbz#2118993 Resolves: rhbz#2121919 Signed-off-by: Jerome Marchand --- .gitignore | 1 + bcc-0.24.0-C9S-Fix-mdflush.patch | 44 - bcc-0.24.0-C9S-libpbf-version-fixes.patch | 297 --- bcc-0.24.0-C9S-remove-ksnoop.patch | 1953 -------------- bcc-0.24.0-Revert-libbpf-1.0-changes.patch | 2331 ----------------- ...tpcts-biosnoop-biotop-Build-fix-for-.patch | 125 - ...atpcts-Build-fixes-on-recent-kernels.patch | 60 - ...ow-to-use-different-cflags-for-bpf-t.patch | 49 - ...-dropped-request-rq_disk-for-kernel-.patch | 158 -- ...-tools-include-blk-mq.h-in-bio-tools.patch | 66 - ...-include-blkdev.h-instead-of-genhd.h.patch | 30 - ...-bpf_pseudo_fd-type-conversion-error.patch | 77 + ...-15-int-to-pointer-conversion-errors.patch | 96 + ...0-Fix-some-documentation-issues-4197.patch | 222 ++ ...ding-with-external-libbpf-package-an.patch | 100 + ...er-fix-an-uninitialized-struct-error.patch | 64 + bcc.spec | 26 +- sources | 2 +- 18 files changed, 574 insertions(+), 5127 deletions(-) delete mode 100644 bcc-0.24.0-C9S-Fix-mdflush.patch delete mode 100644 bcc-0.24.0-C9S-libpbf-version-fixes.patch delete mode 100644 bcc-0.24.0-C9S-remove-ksnoop.patch delete mode 100644 bcc-0.24.0-Revert-libbpf-1.0-changes.patch delete mode 100644 bcc-0.24.0-biolatency-biolatpcts-biosnoop-biotop-Build-fix-for-.patch delete mode 100644 bcc-0.24.0-biolatpcts-Build-fixes-on-recent-kernels.patch delete mode 100644 bcc-0.24.0-libbpf-tools-Allow-to-use-different-cflags-for-bpf-t.patch delete mode 100644 bcc-0.24.0-libbpf-tools-Fix-dropped-request-rq_disk-for-kernel-.patch delete mode 100644 bcc-0.24.0-tools-include-blk-mq.h-in-bio-tools.patch delete mode 100644 bcc-0.24.0-tools-mdflush-include-blkdev.h-instead-of-genhd.h.patch create mode 100644 bcc-0.25.0-Fix-bpf_pseudo_fd-type-conversion-error.patch create mode 100644 bcc-0.25.0-Fix-clang-15-int-to-pointer-conversion-errors.patch create mode 100644 bcc-0.25.0-Fix-some-documentation-issues-4197.patch create mode 100644 bcc-0.25.0-bcc-support-building-with-external-libbpf-package-an.patch create mode 100644 bcc-0.25.0-tools-nfsslower-fix-an-uninitialized-struct-error.patch diff --git a/.gitignore b/.gitignore index 9186af5..063a338 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ /bcc-src-with-submodule.tar.gz /bcc-0.20.0.tar.gz /bcc-0.24.0.tar.gz +/bcc-0.25.0.tar.gz diff --git a/bcc-0.24.0-C9S-Fix-mdflush.patch b/bcc-0.24.0-C9S-Fix-mdflush.patch deleted file mode 100644 index 716789e..0000000 --- a/bcc-0.24.0-C9S-Fix-mdflush.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 5e7543d35596fabd9e5b02b58f8910bf572ca2fa Mon Sep 17 00:00:00 2001 -From: Jerome Marchand -Date: Thu, 7 Oct 2021 17:31:53 +0200 -Subject: [PATCH] C9S: Fix mdflush - -Since kernel commit 309dca309fc ("block: store a block_device pointer -in struct bio") struct bio points again to a block_device and not to a -gendisk directly. However mdflush is looking at the presence or not of -the bio_dev macro to check whether to get the gendisk directly from -the bio or not, which doesn't work anymore since the bio_dev macro -still exists. Since we don't have to deal other ekrnel kernel version -but our own, just use the definition that we use in our kernels. - -Signed-off-by: Jerome Marchand ---- - tools/mdflush.py | 11 ----------- - 1 file changed, 11 deletions(-) - -diff --git a/tools/mdflush.py b/tools/mdflush.py -index 8a23520b..3581d1bf 100755 ---- a/tools/mdflush.py -+++ b/tools/mdflush.py -@@ -35,18 +35,7 @@ int kprobe__md_flush_request(struct pt_regs *ctx, void *mddev, struct bio *bio) - u32 pid = bpf_get_current_pid_tgid() >> 32; - data.pid = pid; - bpf_get_current_comm(&data.comm, sizeof(data.comm)); --/* -- * The following deals with a kernel version change (in mainline 4.14, although -- * it may be backported to earlier kernels) with how the disk name is accessed. -- * We handle both pre- and post-change versions here. Please avoid kernel -- * version tests like this as much as possible: they inflate the code, test, -- * and maintenance burden. -- */ --#ifdef bio_dev -- struct gendisk *bi_disk = bio->bi_disk; --#else - struct gendisk *bi_disk = bio->bi_bdev->bd_disk; --#endif - bpf_probe_read_kernel(&data.disk, sizeof(data.disk), bi_disk->disk_name); - events.perf_submit(ctx, &data, sizeof(data)); - return 0; --- -2.35.1 - diff --git a/bcc-0.24.0-C9S-libpbf-version-fixes.patch b/bcc-0.24.0-C9S-libpbf-version-fixes.patch deleted file mode 100644 index 3c42a52..0000000 --- a/bcc-0.24.0-C9S-libpbf-version-fixes.patch +++ /dev/null @@ -1,297 +0,0 @@ -From a81f219d7f2bfc70dba1eb12208e3e6ab7c81b50 Mon Sep 17 00:00:00 2001 -From: Jerome Marchand -Date: Thu, 24 Mar 2022 16:08:17 +0100 -Subject: [PATCH] C9S: libpbf version fixes - -Revert "bcc: Replace deprecated libbpf APIs" since the libbpf version -provided in C9S doesn't provide the new APIs. - -Remove BPF_MAP_TYPE_BLOOM_FILTER from bps since the libbpf version in -C9S, doesn't provide bloom filter map. - -Add definition of struct bpf_core_relo. ---- - introspection/bps.c | 1 - - src/cc/bcc_btf.cc | 73 +++++++++++++++++++++++++++++++++++++++- - src/cc/libbpf.c | 82 ++++++--------------------------------------- - 3 files changed, 83 insertions(+), 73 deletions(-) - -diff --git a/introspection/bps.c b/introspection/bps.c -index 232b23d4..6ec02e6c 100644 ---- a/introspection/bps.c -+++ b/introspection/bps.c -@@ -80,7 +80,6 @@ static const char * const map_type_strings[] = { - [BPF_MAP_TYPE_RINGBUF] = "ringbuf", - [BPF_MAP_TYPE_INODE_STORAGE] = "inode_storage", - [BPF_MAP_TYPE_TASK_STORAGE] = "task_storage", -- [BPF_MAP_TYPE_BLOOM_FILTER] = "bloom_filter", - }; - - #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) -diff --git a/src/cc/bcc_btf.cc b/src/cc/bcc_btf.cc -index 7f551ae8..c78ba823 100644 ---- a/src/cc/bcc_btf.cc -+++ b/src/cc/bcc_btf.cc -@@ -170,6 +170,77 @@ static int btf_ext_setup_line_info(struct btf_ext *btf_ext) - return btf_ext_setup_info(btf_ext, ¶m); - } - -+/* bpf_core_relo_kind encodes which aspect of captured field/type/enum value -+ * has to be adjusted by relocations. -+ */ -+enum bpf_core_relo_kind { -+ BPF_FIELD_BYTE_OFFSET = 0, /* field byte offset */ -+ BPF_FIELD_BYTE_SIZE = 1, /* field size in bytes */ -+ BPF_FIELD_EXISTS = 2, /* field existence in target kernel */ -+ BPF_FIELD_SIGNED = 3, /* field signedness (0 - unsigned, 1 - signed) */ -+ BPF_FIELD_LSHIFT_U64 = 4, /* bitfield-specific left bitshift */ -+ BPF_FIELD_RSHIFT_U64 = 5, /* bitfield-specific right bitshift */ -+ BPF_TYPE_ID_LOCAL = 6, /* type ID in local BPF object */ -+ BPF_TYPE_ID_TARGET = 7, /* type ID in target kernel */ -+ BPF_TYPE_EXISTS = 8, /* type existence in target kernel */ -+ BPF_TYPE_SIZE = 9, /* type size in bytes */ -+ BPF_ENUMVAL_EXISTS = 10, /* enum value existence in target kernel */ -+ BPF_ENUMVAL_VALUE = 11, /* enum value integer value */ -+}; -+ -+/* The minimum bpf_core_relo checked by the loader -+ * -+ * CO-RE relocation captures the following data: -+ * - insn_off - instruction offset (in bytes) within a BPF program that needs -+ * its insn->imm field to be relocated with actual field info; -+ * - type_id - BTF type ID of the "root" (containing) entity of a relocatable -+ * type or field; -+ * - access_str_off - offset into corresponding .BTF string section. String -+ * interpretation depends on specific relocation kind: -+ * - for field-based relocations, string encodes an accessed field using -+ * a sequence of field and array indices, separated by colon (:). It's -+ * conceptually very close to LLVM's getelementptr ([0]) instruction's -+ * arguments for identifying offset to a field. -+ * - for type-based relocations, strings is expected to be just "0"; -+ * - for enum value-based relocations, string contains an index of enum -+ * value within its enum type; -+ * -+ * Example to provide a better feel. -+ * -+ * struct sample { -+ * int a; -+ * struct { -+ * int b[10]; -+ * }; -+ * }; -+ * -+ * struct sample *s = ...; -+ * int x = &s->a; // encoded as "0:0" (a is field #0) -+ * int y = &s->b[5]; // encoded as "0:1:0:5" (anon struct is field #1, -+ * // b is field #0 inside anon struct, accessing elem #5) -+ * int z = &s[10]->b; // encoded as "10:1" (ptr is used as an array) -+ * -+ * type_id for all relocs in this example will capture BTF type id of -+ * `struct sample`. -+ * -+ * Such relocation is emitted when using __builtin_preserve_access_index() -+ * Clang built-in, passing expression that captures field address, e.g.: -+ * -+ * bpf_probe_read(&dst, sizeof(dst), -+ * __builtin_preserve_access_index(&src->a.b.c)); -+ * -+ * In this case Clang will emit field relocation recording necessary data to -+ * be able to find offset of embedded `a.b.c` field within `src` struct. -+ * -+ * [0] https://llvm.org/docs/LangRef.html#getelementptr-instruction -+ */ -+struct bpf_core_relo { -+ __u32 insn_off; -+ __u32 type_id; -+ __u32 access_str_off; -+ enum bpf_core_relo_kind kind; -+}; -+ - static int btf_ext_setup_core_relos(struct btf_ext *btf_ext) - { - struct btf_ext_sec_setup_param param = { -@@ -597,7 +668,7 @@ int BTF::load(uint8_t *btf_sec, uintptr_t btf_sec_size, - return -1; - } - -- if (btf__load_into_kernel(btf)) { -+ if (btf__load(btf)) { - btf__free(btf); - warning("Loading .BTF section failed\n"); - return -1; -diff --git a/src/cc/libbpf.c b/src/cc/libbpf.c -index e6403299..68af4b35 100644 ---- a/src/cc/libbpf.c -+++ b/src/cc/libbpf.c -@@ -297,25 +297,6 @@ static uint64_t ptr_to_u64(void *ptr) - return (uint64_t) (unsigned long) ptr; - } - --static int libbpf_bpf_map_create(struct bpf_create_map_attr *create_attr) --{ -- LIBBPF_OPTS(bpf_map_create_opts, p); -- -- p.map_flags = create_attr->map_flags; -- p.numa_node = create_attr->numa_node; -- p.btf_fd = create_attr->btf_fd; -- p.btf_key_type_id = create_attr->btf_key_type_id; -- p.btf_value_type_id = create_attr->btf_value_type_id; -- p.map_ifindex = create_attr->map_ifindex; -- if (create_attr->map_type == BPF_MAP_TYPE_STRUCT_OPS) -- p.btf_vmlinux_value_type_id = create_attr->btf_vmlinux_value_type_id; -- else -- p.inner_map_fd = create_attr->inner_map_fd; -- -- return bpf_map_create(create_attr->map_type, create_attr->name, create_attr->key_size, -- create_attr->value_size, create_attr->max_entries, &p); --} -- - int bcc_create_map_xattr(struct bpf_create_map_attr *attr, bool allow_rlimit) - { - unsigned name_len = attr->name ? strlen(attr->name) : 0; -@@ -323,7 +304,7 @@ int bcc_create_map_xattr(struct bpf_create_map_attr *attr, bool allow_rlimit) - - memcpy(map_name, attr->name, min(name_len, BPF_OBJ_NAME_LEN - 1)); - attr->name = map_name; -- int ret = libbpf_bpf_map_create(attr); -+ int ret = bpf_create_map_xattr(attr); - - if (ret < 0 && errno == EPERM) { - if (!allow_rlimit) -@@ -335,7 +316,7 @@ int bcc_create_map_xattr(struct bpf_create_map_attr *attr, bool allow_rlimit) - rl.rlim_max = RLIM_INFINITY; - rl.rlim_cur = rl.rlim_max; - if (setrlimit(RLIMIT_MEMLOCK, &rl) == 0) -- ret = libbpf_bpf_map_create(attr); -+ ret = bpf_create_map_xattr(attr); - } - } - -@@ -345,12 +326,12 @@ int bcc_create_map_xattr(struct bpf_create_map_attr *attr, bool allow_rlimit) - attr->btf_fd = 0; - attr->btf_key_type_id = 0; - attr->btf_value_type_id = 0; -- ret = libbpf_bpf_map_create(attr); -+ ret = bpf_create_map_xattr(attr); - } - - if (ret < 0 && name_len && (errno == E2BIG || errno == EINVAL)) { - map_name[0] = '\0'; -- ret = libbpf_bpf_map_create(attr); -+ ret = bpf_create_map_xattr(attr); - } - - if (ret < 0 && errno == EPERM) { -@@ -363,7 +344,7 @@ int bcc_create_map_xattr(struct bpf_create_map_attr *attr, bool allow_rlimit) - rl.rlim_max = RLIM_INFINITY; - rl.rlim_cur = rl.rlim_max; - if (setrlimit(RLIMIT_MEMLOCK, &rl) == 0) -- ret = libbpf_bpf_map_create(attr); -+ ret = bpf_create_map_xattr(attr); - } - } - return ret; -@@ -627,47 +608,6 @@ int bpf_prog_get_tag(int fd, unsigned long long *ptag) - return 0; - } - --static int libbpf_bpf_prog_load(const struct bpf_load_program_attr *load_attr, -- char *log_buf, size_t log_buf_sz) --{ -- LIBBPF_OPTS(bpf_prog_load_opts, p); -- -- if (!load_attr || !log_buf != !log_buf_sz) { -- errno = EINVAL; -- return -EINVAL; -- } -- -- p.expected_attach_type = load_attr->expected_attach_type; -- switch (load_attr->prog_type) { -- case BPF_PROG_TYPE_STRUCT_OPS: -- case BPF_PROG_TYPE_LSM: -- p.attach_btf_id = load_attr->attach_btf_id; -- break; -- case BPF_PROG_TYPE_TRACING: -- case BPF_PROG_TYPE_EXT: -- p.attach_btf_id = load_attr->attach_btf_id; -- p.attach_prog_fd = load_attr->attach_prog_fd; -- break; -- default: -- p.prog_ifindex = load_attr->prog_ifindex; -- p.kern_version = load_attr->kern_version; -- } -- p.log_level = load_attr->log_level; -- p.log_buf = log_buf; -- p.log_size = log_buf_sz; -- p.prog_btf_fd = load_attr->prog_btf_fd; -- p.func_info_rec_size = load_attr->func_info_rec_size; -- p.func_info_cnt = load_attr->func_info_cnt; -- p.func_info = load_attr->func_info; -- p.line_info_rec_size = load_attr->line_info_rec_size; -- p.line_info_cnt = load_attr->line_info_cnt; -- p.line_info = load_attr->line_info; -- p.prog_flags = load_attr->prog_flags; -- -- return bpf_prog_load(load_attr->prog_type, load_attr->name, load_attr->license, -- load_attr->insns, load_attr->insns_cnt, &p); --} -- - int bcc_prog_load_xattr(struct bpf_load_program_attr *attr, int prog_len, - char *log_buf, unsigned log_buf_size, bool allow_rlimit) - { -@@ -750,7 +690,7 @@ int bcc_prog_load_xattr(struct bpf_load_program_attr *attr, int prog_len, - attr->name = prog_name; - } - -- ret = libbpf_bpf_prog_load(attr, attr_log_buf, attr_log_buf_size); -+ ret = bpf_load_program_xattr(attr, attr_log_buf, attr_log_buf_size); - - // func_info/line_info may not be supported in old kernels. - if (ret < 0 && attr->func_info && errno == EINVAL) { -@@ -761,14 +701,14 @@ int bcc_prog_load_xattr(struct bpf_load_program_attr *attr, int prog_len, - attr->line_info = NULL; - attr->line_info_cnt = 0; - attr->line_info_rec_size = 0; -- ret = libbpf_bpf_prog_load(attr, attr_log_buf, attr_log_buf_size); -+ ret = bpf_load_program_xattr(attr, attr_log_buf, attr_log_buf_size); - } - - // BPF object name is not supported on older Kernels. - // If we failed due to this, clear the name and try again. - if (ret < 0 && name_len && (errno == E2BIG || errno == EINVAL)) { - prog_name[0] = '\0'; -- ret = libbpf_bpf_prog_load(attr, attr_log_buf, attr_log_buf_size); -+ ret = bpf_load_program_xattr(attr, attr_log_buf, attr_log_buf_size); - } - - if (ret < 0 && errno == EPERM) { -@@ -787,7 +727,7 @@ int bcc_prog_load_xattr(struct bpf_load_program_attr *attr, int prog_len, - rl.rlim_max = RLIM_INFINITY; - rl.rlim_cur = rl.rlim_max; - if (setrlimit(RLIMIT_MEMLOCK, &rl) == 0) -- ret = libbpf_bpf_prog_load(attr, attr_log_buf, attr_log_buf_size); -+ ret = bpf_load_program_xattr(attr, attr_log_buf, attr_log_buf_size); - } - } - -@@ -805,7 +745,7 @@ int bcc_prog_load_xattr(struct bpf_load_program_attr *attr, int prog_len, - // If logging is not already enabled, enable it and do the syscall again. - if (attr->log_level == 0) { - attr->log_level = 1; -- ret = libbpf_bpf_prog_load(attr, log_buf, log_buf_size); -+ ret = bpf_load_program_xattr(attr, log_buf, log_buf_size); - } - // Print the log message and return. - bpf_print_hints(ret, log_buf); -@@ -829,7 +769,7 @@ int bcc_prog_load_xattr(struct bpf_load_program_attr *attr, int prog_len, - goto return_result; - } - tmp_log_buf[0] = 0; -- ret = libbpf_bpf_prog_load(attr, tmp_log_buf, tmp_log_buf_size); -+ ret = bpf_load_program_xattr(attr, tmp_log_buf, tmp_log_buf_size); - if (ret < 0 && errno == ENOSPC) { - // Temporary buffer size is not enough. Double it and try again. - free(tmp_log_buf); --- -2.36.1 - diff --git a/bcc-0.24.0-C9S-remove-ksnoop.patch b/bcc-0.24.0-C9S-remove-ksnoop.patch deleted file mode 100644 index 3965a3b..0000000 --- a/bcc-0.24.0-C9S-remove-ksnoop.patch +++ /dev/null @@ -1,1953 +0,0 @@ -From 43a991ffa59acc3d941ef95bb1f20df451a484d8 Mon Sep 17 00:00:00 2001 -From: Jerome Marchand -Date: Wed, 20 Apr 2022 12:42:13 +0200 -Subject: [PATCH] C9S: remove ksnoop - -ksnoop need a more recent libbpf that currently provided on c9s/RHEL 9. - -Signed-off-by: Jerome Marchand ---- - libbpf-tools/Makefile | 1 - - libbpf-tools/ksnoop.bpf.c | 460 ----------------- - libbpf-tools/ksnoop.c | 1013 ------------------------------------- - libbpf-tools/ksnoop.h | 123 ----- - man/man8/ksnoop.8 | 298 ----------- - 5 files changed, 1895 deletions(-) - delete mode 100644 libbpf-tools/ksnoop.bpf.c - delete mode 100644 libbpf-tools/ksnoop.c - delete mode 100644 libbpf-tools/ksnoop.h - delete mode 100644 man/man8/ksnoop.8 - -diff --git a/libbpf-tools/Makefile b/libbpf-tools/Makefile -index 39af95ec..d84e4424 100644 ---- a/libbpf-tools/Makefile -+++ b/libbpf-tools/Makefile -@@ -38,7 +38,6 @@ APPS = \ - gethostlatency \ - hardirqs \ - klockstat \ -- ksnoop \ - llcstat \ - mountsnoop \ - numamove \ -diff --git a/libbpf-tools/ksnoop.bpf.c b/libbpf-tools/ksnoop.bpf.c -deleted file mode 100644 -index 51dfe572..00000000 ---- a/libbpf-tools/ksnoop.bpf.c -+++ /dev/null -@@ -1,460 +0,0 @@ --/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ --/* Copyright (c) 2021, Oracle and/or its affiliates. */ -- --#include "vmlinux.h" -- --#include --#include --#include -- --#include "ksnoop.h" -- --/* For kretprobes, the instruction pointer in the struct pt_regs context -- * is the kretprobe_trampoline. We derive the instruction pointer -- * by pushing it onto a function stack on entry and popping it on return. -- * -- * We could use bpf_get_func_ip(), but "stack mode" - where we -- * specify functions "a", "b and "c" and only want to see a trace if "a" -- * calls "b" and "b" calls "c" - utilizes this stack to determine if trace -- * data should be collected. -- */ --#define FUNC_MAX_STACK_DEPTH 16 --/* used to convince verifier we do not stray outside of array bounds */ --#define FUNC_STACK_DEPTH_MASK (FUNC_MAX_STACK_DEPTH - 1) -- --#ifndef ENOSPC --#define ENOSPC 28 --#endif -- --struct func_stack { -- __u64 task; -- __u64 ips[FUNC_MAX_STACK_DEPTH]; -- __u8 stack_depth; --}; -- --#define MAX_TASKS 2048 -- --/* function call stack hashed on a per-task key */ --struct { -- __uint(type, BPF_MAP_TYPE_HASH); -- /* function call stack for functions we are tracing */ -- __uint(max_entries, MAX_TASKS); -- __type(key, __u64); -- __type(value, struct func_stack); --} ksnoop_func_stack SEC(".maps"); -- --/* per-cpu trace info hashed on function address */ --struct { -- __uint(type, BPF_MAP_TYPE_PERCPU_HASH); -- __uint(max_entries, MAX_FUNC_TRACES); -- __type(key, __u64); -- __type(value, struct trace); --} ksnoop_func_map SEC(".maps"); -- --struct { -- __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); -- __uint(value_size, sizeof(int)); -- __uint(key_size, sizeof(int)); --} ksnoop_perf_map SEC(".maps"); -- --static void clear_trace(struct trace *trace) --{ -- __builtin_memset(&trace->trace_data, 0, sizeof(trace->trace_data)); -- trace->data_flags = 0; -- trace->buf_len = 0; --} -- --static struct trace *get_trace(struct pt_regs *ctx, bool entry) --{ -- __u8 stack_depth, last_stack_depth; -- struct func_stack *func_stack; -- __u64 ip, last_ip = 0, task; -- struct trace *trace; -- -- task = bpf_get_current_task(); -- -- func_stack = bpf_map_lookup_elem(&ksnoop_func_stack, &task); -- if (!func_stack) { -- struct func_stack new_stack = { .task = task }; -- -- bpf_map_update_elem(&ksnoop_func_stack, &task, &new_stack, -- BPF_NOEXIST); -- func_stack = bpf_map_lookup_elem(&ksnoop_func_stack, &task); -- if (!func_stack) -- return NULL; -- } -- -- stack_depth = func_stack->stack_depth; -- if (stack_depth > FUNC_MAX_STACK_DEPTH) -- return NULL; -- -- if (entry) { -- ip = KSNOOP_IP_FIX(PT_REGS_IP_CORE(ctx)); -- if (stack_depth >= FUNC_MAX_STACK_DEPTH - 1) -- return NULL; -- /* verifier doesn't like using "stack_depth - 1" as array index -- * directly. -- */ -- last_stack_depth = stack_depth - 1; -- /* get address of last function we called */ -- if (last_stack_depth >= 0 && -- last_stack_depth < FUNC_MAX_STACK_DEPTH) -- last_ip = func_stack->ips[last_stack_depth]; -- /* push ip onto stack. return will pop it. */ -- func_stack->ips[stack_depth] = ip; -- /* mask used in case bounds checks are optimized out */ -- stack_depth = (stack_depth + 1) & FUNC_STACK_DEPTH_MASK; -- func_stack->stack_depth = stack_depth; -- /* rather than zero stack entries on popping, we zero the -- * (stack_depth + 1)'th entry when pushing the current -- * entry. The reason we take this approach is that -- * when tracking the set of functions we returned from, -- * we want the history of functions we returned from to -- * be preserved. -- */ -- if (stack_depth < FUNC_MAX_STACK_DEPTH) -- func_stack->ips[stack_depth] = 0; -- } else { -- if (stack_depth == 0 || stack_depth >= FUNC_MAX_STACK_DEPTH) -- return NULL; -- last_stack_depth = stack_depth; -- /* get address of last function we returned from */ -- if (last_stack_depth >= 0 && -- last_stack_depth < FUNC_MAX_STACK_DEPTH) -- last_ip = func_stack->ips[last_stack_depth]; -- if (stack_depth > 0) { -- /* logical OR convinces verifier that we don't -- * end up with a < 0 value, translating to 0xff -- * and an outside of map element access. -- */ -- stack_depth = (stack_depth - 1) & FUNC_STACK_DEPTH_MASK; -- } -- /* retrieve ip from stack as IP in pt_regs is -- * bpf kretprobe trampoline address. -- */ -- if (stack_depth >= 0 && stack_depth < FUNC_MAX_STACK_DEPTH) -- ip = func_stack->ips[stack_depth]; -- if (stack_depth >= 0 && stack_depth < FUNC_MAX_STACK_DEPTH) -- func_stack->stack_depth = stack_depth; -- } -- -- trace = bpf_map_lookup_elem(&ksnoop_func_map, &ip); -- if (!trace) -- return NULL; -- -- /* we may stash data on entry since predicates are a mix -- * of entry/return; in such cases, trace->flags specifies -- * KSNOOP_F_STASH, and we will output stashed data on return. -- * If returning, make sure we don't clear our stashed data. -- */ -- if (!entry && (trace->flags & KSNOOP_F_STASH)) { -- /* skip clearing trace data */ -- if (!(trace->data_flags & KSNOOP_F_STASHED)) { -- /* predicate must have failed */ -- return NULL; -- } -- /* skip clearing trace data */ -- } else { -- /* clear trace data before starting. */ -- clear_trace(trace); -- } -- -- if (entry) { -- /* if in stack mode, check if previous fn matches */ -- if (trace->prev_ip && trace->prev_ip != last_ip) -- return NULL; -- /* if tracing intermediate fn in stack of fns, stash data. */ -- if (trace->next_ip) -- trace->data_flags |= KSNOOP_F_STASH; -- /* we may stash data on entry since predicates are a mix -- * of entry/return; in such cases, trace->flags specifies -- * KSNOOP_F_STASH, and we will output stashed data on return. -- */ -- if (trace->flags & KSNOOP_F_STASH) -- trace->data_flags |= KSNOOP_F_STASH; -- /* otherwise the data is outputted (because we've reached -- * the last fn in the set of fns specified). -- */ -- } else { -- /* In stack mode, check if next fn matches the last fn -- * we returned from; i.e. "a" called "b", and now -- * we're at "a", was the last fn we returned from "b"? -- * If so, stash data for later display (when we reach the -- * first fn in the set of stack fns). -- */ -- if (trace->next_ip && trace->next_ip != last_ip) -- return NULL; -- if (trace->prev_ip) -- trace->data_flags |= KSNOOP_F_STASH; -- /* If there is no "prev" function, i.e. we are at the -- * first function in a set of stack functions, the trace -- * info is shown (along with any stashed info associated -- * with callers). -- */ -- } -- trace->task = task; -- return trace; --} -- --static void output_trace(struct pt_regs *ctx, struct trace *trace) --{ -- __u16 trace_len; -- -- if (trace->buf_len == 0) -- goto skip; -- -- /* we may be simply stashing values, and will report later */ -- if (trace->data_flags & KSNOOP_F_STASH) { -- trace->data_flags &= ~KSNOOP_F_STASH; -- trace->data_flags |= KSNOOP_F_STASHED; -- return; -- } -- /* we may be outputting earlier stashed data */ -- if (trace->data_flags & KSNOOP_F_STASHED) -- trace->data_flags &= ~KSNOOP_F_STASHED; -- -- /* trim perf event size to only contain data we've recorded. */ -- trace_len = sizeof(*trace) + trace->buf_len - MAX_TRACE_BUF; -- -- if (trace_len <= sizeof(*trace)) -- bpf_perf_event_output(ctx, &ksnoop_perf_map, -- BPF_F_CURRENT_CPU, -- trace, trace_len); --skip: -- clear_trace(trace); --} -- --static void output_stashed_traces(struct pt_regs *ctx, -- struct trace *currtrace, -- bool entry) --{ -- struct func_stack *func_stack; -- struct trace *trace = NULL; -- __u8 i; -- __u64 task = 0; -- -- task = bpf_get_current_task(); -- func_stack = bpf_map_lookup_elem(&ksnoop_func_stack, &task); -- if (!func_stack) -- return; -- -- if (entry) { -- /* iterate from bottom to top of stack, outputting stashed -- * data we find. This corresponds to the set of functions -- * we called before the current function. -- */ -- for (i = 0; -- i < func_stack->stack_depth - 1 && i < FUNC_MAX_STACK_DEPTH; -- i++) { -- trace = bpf_map_lookup_elem(&ksnoop_func_map, -- &func_stack->ips[i]); -- if (!trace || !(trace->data_flags & KSNOOP_F_STASHED)) -- break; -- if (trace->task != task) -- return; -- output_trace(ctx, trace); -- } -- } else { -- /* iterate from top to bottom of stack, outputting stashed -- * data we find. This corresponds to the set of functions -- * that returned prior to the current returning function. -- */ -- for (i = FUNC_MAX_STACK_DEPTH; i > 0; i--) { -- __u64 ip; -- -- ip = func_stack->ips[i]; -- if (!ip) -- continue; -- trace = bpf_map_lookup_elem(&ksnoop_func_map, &ip); -- if (!trace || !(trace->data_flags & KSNOOP_F_STASHED)) -- break; -- if (trace->task != task) -- return; -- output_trace(ctx, trace); -- } -- } -- /* finally output the current trace info */ -- output_trace(ctx, currtrace); --} -- --static __u64 get_arg(struct pt_regs *ctx, enum arg argnum) --{ -- switch (argnum) { -- case KSNOOP_ARG1: -- return PT_REGS_PARM1_CORE(ctx); -- case KSNOOP_ARG2: -- return PT_REGS_PARM2_CORE(ctx); -- case KSNOOP_ARG3: -- return PT_REGS_PARM3_CORE(ctx); -- case KSNOOP_ARG4: -- return PT_REGS_PARM4_CORE(ctx); -- case KSNOOP_ARG5: -- return PT_REGS_PARM5_CORE(ctx); -- case KSNOOP_RETURN: -- return PT_REGS_RC_CORE(ctx); -- default: -- return 0; -- } --} -- --static int ksnoop(struct pt_regs *ctx, bool entry) --{ -- void *data_ptr = NULL; -- struct trace *trace; -- __u64 data; -- __u32 currpid; -- int ret; -- __u8 i; -- -- trace = get_trace(ctx, entry); -- if (!trace) -- return 0; -- -- /* make sure we want events from this pid */ -- currpid = bpf_get_current_pid_tgid(); -- if (trace->filter_pid && trace->filter_pid != currpid) -- return 0; -- trace->pid = currpid; -- -- trace->cpu = bpf_get_smp_processor_id(); -- trace->time = bpf_ktime_get_ns(); -- -- trace->data_flags &= ~(KSNOOP_F_ENTRY | KSNOOP_F_RETURN); -- if (entry) -- trace->data_flags |= KSNOOP_F_ENTRY; -- else -- trace->data_flags |= KSNOOP_F_RETURN; -- -- -- for (i = 0; i < MAX_TRACES; i++) { -- struct trace_data *currdata; -- struct value *currtrace; -- char *buf_offset = NULL; -- __u32 tracesize; -- -- currdata = &trace->trace_data[i]; -- currtrace = &trace->traces[i]; -- -- if ((entry && !base_arg_is_entry(currtrace->base_arg)) || -- (!entry && base_arg_is_entry(currtrace->base_arg))) -- continue; -- -- /* skip void (unused) trace arguments, ensuring not to -- * skip "void *". -- */ -- if (currtrace->type_id == 0 && -- !(currtrace->flags & KSNOOP_F_PTR)) -- continue; -- -- data = get_arg(ctx, currtrace->base_arg); -- -- /* look up member value and read into data field. */ -- if (currtrace->flags & KSNOOP_F_MEMBER) { -- if (currtrace->offset) -- data += currtrace->offset; -- -- /* member is a pointer; read it in */ -- if (currtrace->flags & KSNOOP_F_PTR) { -- void *dataptr = (void *)data; -- -- ret = bpf_probe_read(&data, sizeof(data), -- dataptr); -- if (ret) { -- currdata->err_type_id = -- currtrace->type_id; -- currdata->err = ret; -- continue; -- } -- currdata->raw_value = data; -- } else if (currtrace->size <= -- sizeof(currdata->raw_value)) { -- /* read member value for predicate comparison */ -- bpf_probe_read(&currdata->raw_value, -- currtrace->size, -- (void*)data); -- } -- } else { -- currdata->raw_value = data; -- } -- -- /* simple predicate evaluation: if any predicate fails, -- * skip all tracing for this function. -- */ -- if (currtrace->flags & KSNOOP_F_PREDICATE_MASK) { -- bool ok = false; -- -- if (currtrace->flags & KSNOOP_F_PREDICATE_EQ && -- currdata->raw_value == currtrace->predicate_value) -- ok = true; -- -- if (currtrace->flags & KSNOOP_F_PREDICATE_NOTEQ && -- currdata->raw_value != currtrace->predicate_value) -- ok = true; -- -- if (currtrace->flags & KSNOOP_F_PREDICATE_GT && -- currdata->raw_value > currtrace->predicate_value) -- ok = true; -- -- if (currtrace->flags & KSNOOP_F_PREDICATE_LT && -- currdata->raw_value < currtrace->predicate_value) -- ok = true; -- -- if (!ok) { -- clear_trace(trace); -- return 0; -- } -- } -- -- if (currtrace->flags & (KSNOOP_F_PTR | KSNOOP_F_MEMBER)) -- data_ptr = (void *)data; -- else -- data_ptr = &data; -- -- if (trace->buf_len + MAX_TRACE_DATA >= MAX_TRACE_BUF) -- break; -- -- buf_offset = &trace->buf[trace->buf_len]; -- if (buf_offset > &trace->buf[MAX_TRACE_BUF]) { -- currdata->err_type_id = currtrace->type_id; -- currdata->err = -ENOSPC; -- continue; -- } -- currdata->buf_offset = trace->buf_len; -- -- tracesize = currtrace->size; -- if (tracesize > MAX_TRACE_DATA) -- tracesize = MAX_TRACE_DATA; -- ret = bpf_probe_read(buf_offset, tracesize, data_ptr); -- if (ret < 0) { -- currdata->err_type_id = currtrace->type_id; -- currdata->err = ret; -- continue; -- } else { -- currdata->buf_len = tracesize; -- trace->buf_len += tracesize; -- } -- } -- -- /* show accumulated stashed traces (if any) */ -- if ((entry && trace->prev_ip && !trace->next_ip) || -- (!entry && trace->next_ip && !trace->prev_ip)) -- output_stashed_traces(ctx, trace, entry); -- else -- output_trace(ctx, trace); -- -- return 0; --} -- --SEC("kprobe/foo") --int kprobe_entry(struct pt_regs *ctx) --{ -- return ksnoop(ctx, true); --} -- --SEC("kretprobe/foo") --int kprobe_return(struct pt_regs *ctx) --{ -- return ksnoop(ctx, false); --} -- --char _license[] SEC("license") = "Dual BSD/GPL"; -diff --git a/libbpf-tools/ksnoop.c b/libbpf-tools/ksnoop.c -deleted file mode 100644 -index a5f59a0f..00000000 ---- a/libbpf-tools/ksnoop.c -+++ /dev/null -@@ -1,1013 +0,0 @@ --/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ --/* Copyright (c) 2021, Oracle and/or its affiliates. */ -- --#include --#include --#include --#include --#include --#include --#include -- --#include --#include --#include -- --#include "ksnoop.h" --#include "ksnoop.skel.h" -- --#ifndef KSNOOP_VERSION --#define KSNOOP_VERSION "0.1" --#endif -- --static volatile sig_atomic_t exiting = 0; -- --static struct btf *vmlinux_btf; --static const char *bin_name; --static int pages = PAGES_DEFAULT; -- --enum log_level { -- DEBUG, -- WARN, -- ERROR, --}; -- --static enum log_level log_level = WARN; --static bool verbose = false; -- --static __u32 filter_pid; --static bool stack_mode; -- --#define libbpf_errstr(val) strerror(-libbpf_get_error(val)) -- --static void __p(enum log_level level, char *level_str, char *fmt, ...) --{ -- va_list ap; -- -- if (level < log_level) -- return; -- va_start(ap, fmt); -- fprintf(stderr, "%s: ", level_str); -- vfprintf(stderr, fmt, ap); -- fprintf(stderr, "\n"); -- va_end(ap); -- fflush(stderr); --} -- --#define p_err(fmt, ...) __p(ERROR, "Error", fmt, ##__VA_ARGS__) --#define p_warn(fmt, ...) __p(WARNING, "Warn", fmt, ##__VA_ARGS__) --#define p_debug(fmt, ...) __p(DEBUG, "Debug", fmt, ##__VA_ARGS__) -- --static int do_version(int argc, char **argv) --{ -- printf("%s v%s\n", bin_name, KSNOOP_VERSION); -- return 0; --} -- --static int cmd_help(int argc, char **argv) --{ -- fprintf(stderr, -- "Usage: %s [OPTIONS] [COMMAND | help] FUNC\n" -- " COMMAND := { trace | info }\n" -- " FUNC := { name | name(ARG[,ARG]*) }\n" -- " ARG := { arg | arg [PRED] | arg->member [PRED] }\n" -- " PRED := { == | != | > | >= | < | <= value }\n" -- " OPTIONS := { {-d|--debug} | {-v|--verbose} | {-V|--version} |\n" -- " {-p|--pid filter_pid}|\n" -- " {-P|--pages nr_pages} }\n" -- " {-s|--stack}\n", -- bin_name); -- fprintf(stderr, -- "Examples:\n" -- " %s info ip_send_skb\n" -- " %s trace ip_send_skb\n" -- " %s trace \"ip_send_skb(skb, return)\"\n" -- " %s trace \"ip_send_skb(skb->sk, return)\"\n" -- " %s trace \"ip_send_skb(skb->len > 128, skb)\"\n" -- " %s trace -s udp_sendmsg ip_send_skb\n", -- bin_name, bin_name, bin_name, bin_name, bin_name, bin_name); -- return 0; --} -- --static void usage(void) --{ -- cmd_help(0, NULL); -- exit(1); --} -- --static void type_to_value(struct btf *btf, char *name, __u32 type_id, -- struct value *val) --{ -- const struct btf_type *type; -- __s32 id = type_id; -- -- if (strlen(val->name) == 0) { -- if (name) -- strncpy(val->name, name, -- sizeof(val->name) - 1); -- else -- val->name[0] = '\0'; -- } -- do { -- type = btf__type_by_id(btf, id); -- -- switch (BTF_INFO_KIND(type->info)) { -- case BTF_KIND_CONST: -- case BTF_KIND_VOLATILE: -- case BTF_KIND_RESTRICT: -- id = type->type; -- break; -- case BTF_KIND_PTR: -- val->flags |= KSNOOP_F_PTR; -- id = type->type; -- break; -- default: -- val->type_id = id; -- goto done; -- } -- } while (id >= 0); -- -- val->type_id = KSNOOP_ID_UNKNOWN; -- return; --done: -- val->size = btf__resolve_size(btf, val->type_id); --} -- --static int member_to_value(struct btf *btf, const char *name, __u32 type_id, -- struct value *val, int lvl) --{ -- const struct btf_member *member; -- const struct btf_type *type; -- const char *pname; -- __s32 id = type_id; -- int i, nmembers; -- __u8 kind; -- -- /* type_to_value has already stripped qualifiers, so -- * we either have a base type, a struct, union, etc. -- * Only struct/unions have named members so anything -- * else is invalid. -- */ -- p_debug("Looking for member '%s' in type id %d", name, type_id); -- type = btf__type_by_id(btf, id); -- pname = btf__str_by_offset(btf, type->name_off); -- if (strlen(pname) == 0) -- pname = ""; -- -- kind = BTF_INFO_KIND(type->info); -- switch (kind) { -- case BTF_KIND_STRUCT: -- case BTF_KIND_UNION: -- nmembers = BTF_INFO_VLEN(type->info); -- p_debug("Checking %d members...", nmembers); -- for (member = (struct btf_member *)(type + 1), i = 0; -- i < nmembers; -- member++, i++) { -- const char *mname; -- __u16 offset; -- -- type = btf__type_by_id(btf, member->type); -- mname = btf__str_by_offset(btf, member->name_off); -- offset = member->offset / 8; -- -- p_debug("Checking member '%s' type %d offset %d", -- mname, member->type, offset); -- -- /* anonymous struct member? */ -- kind = BTF_INFO_KIND(type->info); -- if (strlen(mname) == 0 && -- (kind == BTF_KIND_STRUCT || -- kind == BTF_KIND_UNION)) { -- p_debug("Checking anon struct/union %d", -- member->type); -- val->offset += offset; -- if (!member_to_value(btf, name, member->type, -- val, lvl + 1)) -- return 0; -- val->offset -= offset; -- continue; -- } -- -- if (strcmp(mname, name) == 0) { -- val->offset += offset; -- val->flags |= KSNOOP_F_MEMBER; -- type_to_value(btf, NULL, member->type, val); -- p_debug("Member '%s', offset %d, flags %x size %d", -- mname, val->offset, val->flags, -- val->size); -- return 0; -- } -- } -- if (lvl > 0) -- break; -- p_err("No member '%s' found in %s [%d], offset %d", name, pname, -- id, val->offset); -- break; -- default: -- p_err("'%s' is not a struct/union", pname); -- break; -- } -- return -ENOENT; --} -- --static int get_func_btf(struct btf *btf, struct func *func) --{ -- const struct btf_param *param; -- const struct btf_type *type; -- __u8 i; -- -- func->id = btf__find_by_name_kind(btf, func->name, BTF_KIND_FUNC); -- if (func->id <= 0) { -- p_err("Cannot find function '%s' in BTF: %s", -- func->name, strerror(-func->id)); -- return -ENOENT; -- } -- type = btf__type_by_id(btf, func->id); -- if (libbpf_get_error(type) || -- BTF_INFO_KIND(type->info) != BTF_KIND_FUNC) { -- p_err("Error looking up function type via id '%d'", func->id); -- return -EINVAL; -- } -- type = btf__type_by_id(btf, type->type); -- if (libbpf_get_error(type) || -- BTF_INFO_KIND(type->info) != BTF_KIND_FUNC_PROTO) { -- p_err("Error looking up function proto type via id '%d'", -- func->id); -- return -EINVAL; -- } -- for (param = (struct btf_param *)(type + 1), i = 0; -- i < BTF_INFO_VLEN(type->info) && i < MAX_ARGS; -- param++, i++) { -- type_to_value(btf, -- (char *)btf__str_by_offset(btf, param->name_off), -- param->type, &func->args[i]); -- p_debug("arg #%d: ", -- i + 1, func->args[i].name, func->args[i].type_id); -- } -- -- /* real number of args, even if it is > number we recorded. */ -- func->nr_args = BTF_INFO_VLEN(type->info); -- -- type_to_value(btf, KSNOOP_RETURN_NAME, type->type, -- &func->args[KSNOOP_RETURN]); -- p_debug("return value: type id '%u'>", -- func->args[KSNOOP_RETURN].type_id); -- return 0; --} -- --static int predicate_to_value(char *predicate, struct value *val) --{ -- char pred[MAX_STR]; -- long v; -- -- if (!predicate) -- return 0; -- -- p_debug("checking predicate '%s' for '%s'", predicate, val->name); -- -- if (sscanf(predicate, "%[!=><]%li", pred, &v) != 2) { -- p_err("Invalid specification; expected predicate, not '%s'", -- predicate); -- return -EINVAL; -- } -- if (!(val->flags & KSNOOP_F_PTR) && -- (val->size == 0 || val->size > sizeof(__u64))) { -- p_err("'%s' (size %d) does not support predicate comparison", -- val->name, val->size); -- return -EINVAL; -- } -- val->predicate_value = (__u64)v; -- -- if (strcmp(pred, "==") == 0) { -- val->flags |= KSNOOP_F_PREDICATE_EQ; -- goto out; -- } else if (strcmp(pred, "!=") == 0) { -- val->flags |= KSNOOP_F_PREDICATE_NOTEQ; -- goto out; -- } -- if (pred[0] == '>') -- val->flags |= KSNOOP_F_PREDICATE_GT; -- else if (pred[0] == '<') -- val->flags |= KSNOOP_F_PREDICATE_LT; -- -- if (strlen(pred) == 1) -- goto out; -- -- if (pred[1] != '=') { -- p_err("Invalid predicate specification '%s'", predicate); -- return -EINVAL; -- } -- val->flags |= KSNOOP_F_PREDICATE_EQ; -- --out: -- p_debug("predicate '%s', flags 0x%x value %x", -- pred, val->flags, val->predicate_value); -- -- return 0; --} -- --static int trace_to_value(struct btf *btf, struct func *func, char *argname, -- char *membername, char *predicate, struct value *val) --{ -- __u8 i; -- -- if (strlen(membername) > 0) -- snprintf(val->name, sizeof(val->name), "%s->%s", -- argname, membername); -- else -- strncpy(val->name, argname, sizeof(val->name)); -- -- for (i = 0; i < MAX_TRACES; i++) { -- if (!func->args[i].name) -- continue; -- if (strcmp(argname, func->args[i].name) != 0) -- continue; -- p_debug("setting base arg for val %s to %d", val->name, i); -- val->base_arg = i; -- -- if (strlen(membername) > 0) { -- if (member_to_value(btf, membername, -- func->args[i].type_id, val, 0)) -- return -ENOENT; -- } else { -- val->type_id = func->args[i].type_id; -- val->flags |= func->args[i].flags; -- val->size = func->args[i].size; -- } -- return predicate_to_value(predicate, val); -- } -- p_err("Could not find '%s' in arguments/return value for '%s'", -- argname, func->name); -- return -ENOENT; --} -- --static struct btf *get_btf(const char *name) --{ -- struct btf *mod_btf; -- -- p_debug("getting BTF for %s", -- name && strlen(name) > 0 ? name : "vmlinux"); -- -- if (!vmlinux_btf) { -- vmlinux_btf = libbpf_find_kernel_btf(); -- if (libbpf_get_error(vmlinux_btf)) { -- p_err("No BTF, cannot determine type info: %s", -- libbpf_errstr(vmlinux_btf)); -- return NULL; -- } -- } -- if (!name || strlen(name) == 0) -- return vmlinux_btf; -- -- mod_btf = btf__load_module_btf(name, vmlinux_btf); -- if (libbpf_get_error(mod_btf)) { -- p_err("No BTF for module '%s': %s", -- name, libbpf_errstr(mod_btf)); -- return NULL; -- } -- return mod_btf; --} -- --static void copy_without_spaces(char *target, char *src) --{ -- for (; *src != '\0'; src++) -- if (!isspace(*src)) -- *(target++) = *src; -- *target = '\0'; --} -- --static char *type_id_to_str(struct btf *btf, __s32 type_id, char *str) --{ -- const struct btf_type *type; -- const char *name = ""; -- char *prefix = ""; -- char *suffix = " "; -- char *ptr = ""; -- -- str[0] = '\0'; -- -- switch (type_id) { -- case 0: -- name = "void"; -- break; -- case KSNOOP_ID_UNKNOWN: -- name = "?"; -- break; -- default: -- do { -- type = btf__type_by_id(btf, type_id); -- -- if (libbpf_get_error(type)) { -- name = "?"; -- break; -- } -- switch (BTF_INFO_KIND(type->info)) { -- case BTF_KIND_CONST: -- case BTF_KIND_VOLATILE: -- case BTF_KIND_RESTRICT: -- type_id = type->type; -- break; -- case BTF_KIND_PTR: -- ptr = "* "; -- type_id = type->type; -- break; -- case BTF_KIND_ARRAY: -- suffix = "[]"; -- type_id = type->type; -- break; -- case BTF_KIND_STRUCT: -- prefix = "struct "; -- name = btf__str_by_offset(btf, type->name_off); -- break; -- case BTF_KIND_UNION: -- prefix = "union "; -- name = btf__str_by_offset(btf, type->name_off); -- break; -- case BTF_KIND_ENUM: -- prefix = "enum "; -- name = btf__str_by_offset(btf, type->name_off); -- break; -- case BTF_KIND_TYPEDEF: -- name = btf__str_by_offset(btf, type->name_off); -- break; -- default: -- name = btf__str_by_offset(btf, type->name_off); -- break; -- } -- } while (type_id >= 0 && strlen(name) == 0); -- break; -- } -- snprintf(str, MAX_STR, "%s%s%s%s", prefix, name, suffix, ptr); -- -- return str; --} -- --static char *value_to_str(struct btf *btf, struct value *val, char *str) --{ -- -- str = type_id_to_str(btf, val->type_id, str); -- if (val->flags & KSNOOP_F_PTR) -- strncat(str, "*", MAX_STR); -- if (strlen(val->name) > 0 && -- strcmp(val->name, KSNOOP_RETURN_NAME) != 0) -- strncat(str, val->name, MAX_STR); -- -- return str; --} -- --/* based heavily on bpf_object__read_kallsyms_file() in libbpf.c */ --static int get_func_ip_mod(struct func *func) --{ -- char sym_type, sym_name[MAX_STR], mod_info[MAX_STR]; -- unsigned long long sym_addr; -- int ret, err = 0; -- FILE *f; -- -- f = fopen("/proc/kallsyms", "r"); -- if (!f) { -- err = errno; -- p_err("failed to open /proc/kallsyms: %d", strerror(err)); -- return err; -- } -- -- while (true) { -- ret = fscanf(f, "%llx %c %128s%[^\n]\n", -- &sym_addr, &sym_type, sym_name, mod_info); -- if (ret == EOF && feof(f)) -- break; -- if (ret < 3) { -- p_err("failed to read kallsyms entry: %d", ret); -- err = -EINVAL; -- goto out; -- } -- if (strcmp(func->name, sym_name) != 0) -- continue; -- func->ip = sym_addr; -- func->mod[0] = '\0'; -- /* get module name from [modname] */ -- if (ret == 4) { -- if (sscanf(mod_info, "%*[\t ][%[^]]", func->mod) < 1) { -- p_err("failed to read module name"); -- err = -EINVAL; -- goto out; -- } -- } -- p_debug("%s = ", func->name, func->ip, -- strlen(func->mod) > 0 ? func->mod : "vmlinux"); -- break; -- } --out: -- fclose(f); -- return err; --} -- --static void trace_printf(void *ctx, const char *fmt, va_list args) --{ -- vprintf(fmt, args); --} -- --#define VALID_NAME "%[A-Za-z0-9\\-_]" --#define ARGDATA "%[^)]" -- --static int parse_trace(char *str, struct trace *trace) --{ -- __u8 i, nr_predicates = 0, nr_entry = 0, nr_return = 0; -- char argname[MAX_NAME], membername[MAX_NAME]; -- char tracestr[MAX_STR], argdata[MAX_STR]; -- struct func *func = &trace->func; -- struct btf_dump_opts opts = { }; -- char *arg, *saveptr; -- int ret; -- -- copy_without_spaces(tracestr, str); -- -- p_debug("Parsing trace '%s'", tracestr); -- -- trace->filter_pid = (__u32)filter_pid; -- if (filter_pid) -- p_debug("Using pid %lu as filter", trace->filter_pid); -- -- trace->btf = vmlinux_btf; -- -- ret = sscanf(tracestr, VALID_NAME "(" ARGDATA ")", func->name, argdata); -- if (ret <= 0) -- usage(); -- if (ret == 1) { -- if (strlen(tracestr) > strlen(func->name)) { -- p_err("Invalid function specification '%s'", tracestr); -- usage(); -- } -- argdata[0] = '\0'; -- p_debug("got func '%s'", func->name); -- } else { -- if (strlen(tracestr) > -- strlen(func->name) + strlen(argdata) + 2) { -- p_err("Invalid function specification '%s'", tracestr); -- usage(); -- } -- p_debug("got func '%s', args '%s'", func->name, argdata); -- trace->flags |= KSNOOP_F_CUSTOM; -- } -- -- ret = get_func_ip_mod(func); -- if (ret) { -- p_err("could not get address of '%s'", func->name); -- return ret; -- } -- trace->btf = get_btf(func->mod); -- if (libbpf_get_error(trace->btf)) { -- p_err("could not get BTF for '%s': %s", -- strlen(func->mod) ? func->mod : "vmlinux", -- libbpf_errstr(trace->btf)); -- return -ENOENT; -- } -- trace->dump = btf_dump__new(trace->btf, NULL, &opts, trace_printf); -- if (libbpf_get_error(trace->dump)) { -- p_err("could not create BTF dump : %n", -- libbpf_errstr(trace->btf)); -- return -EINVAL; -- } -- -- ret = get_func_btf(trace->btf, func); -- if (ret) { -- p_debug("unexpected return value '%d' getting function", ret); -- return ret; -- } -- -- for (arg = strtok_r(argdata, ",", &saveptr), i = 0; -- arg; -- arg = strtok_r(NULL, ",", &saveptr), i++) { -- char *predicate = NULL; -- -- ret = sscanf(arg, VALID_NAME "->" VALID_NAME, -- argname, membername); -- if (ret == 2) { -- if (strlen(arg) > -- strlen(argname) + strlen(membername) + 2) { -- predicate = arg + strlen(argname) + -- strlen(membername) + 2; -- } -- p_debug("'%s' dereferences '%s', predicate '%s'", -- argname, membername, predicate); -- } else { -- if (strlen(arg) > strlen(argname)) -- predicate = arg + strlen(argname); -- p_debug("'%s' arg, predcate '%s'", argname, predicate); -- membername[0] = '\0'; -- } -- -- if (i >= MAX_TRACES) { -- p_err("Too many arguments; up to %d are supported", -- MAX_TRACES); -- return -EINVAL; -- } -- if (trace_to_value(trace->btf, func, argname, membername, -- predicate, &trace->traces[i])) -- return -EINVAL; -- -- if (predicate) -- nr_predicates++; -- if (trace->traces[i].base_arg == KSNOOP_RETURN) -- nr_return++; -- else -- nr_entry++; -- trace->nr_traces++; -- } -- -- if (trace->nr_traces > 0) { -- trace->flags |= KSNOOP_F_CUSTOM; -- p_debug("custom trace with %d args", trace->nr_traces); -- -- /* If we have one or more predicates _and_ references to -- * entry and return values, we need to activate "stash" -- * mode where arg traces are stored on entry and not -- * sent until return to ensure predicates are satisfied. -- */ -- if (nr_predicates > 0 && nr_entry > 0 && nr_return > 0) { -- trace->flags |= KSNOOP_F_STASH; -- p_debug("activating stash mode on entry"); -- } -- } else { -- p_debug("Standard trace, function with %d arguments", -- func->nr_args); -- /* copy function arg/return value to trace specification. */ -- memcpy(trace->traces, func->args, sizeof(trace->traces)); -- for (i = 0; i < MAX_TRACES; i++) -- trace->traces[i].base_arg = i; -- trace->nr_traces = MAX_TRACES; -- } -- -- return 0; --} -- --static int parse_traces(int argc, char **argv, struct trace **traces) --{ -- __u8 i; -- -- if (argc == 0) -- usage(); -- -- if (argc > MAX_FUNC_TRACES) { -- p_err("A maximum of %d traces are supported", MAX_FUNC_TRACES); -- return -EINVAL; -- } -- *traces = calloc(argc, sizeof(struct trace)); -- if (!*traces) { -- p_err("Could not allocate %d traces", argc); -- return -ENOMEM; -- } -- for (i = 0; i < argc; i++) { -- if (parse_trace(argv[i], &((*traces)[i]))) -- return -EINVAL; -- if (!stack_mode || i == 0) -- continue; -- /* tell stack mode trace which function to expect next */ -- (*traces)[i].prev_ip = (*traces)[i-1].func.ip; -- (*traces)[i-1].next_ip = (*traces)[i].func.ip; -- } -- return i; --} -- --static int cmd_info(int argc, char **argv) --{ -- struct trace *traces = NULL; -- char str[MAX_STR]; -- int nr_traces; -- __u8 i, j; -- -- nr_traces = parse_traces(argc, argv, &traces); -- if (nr_traces < 0) -- return nr_traces; -- -- for (i = 0; i < nr_traces; i++) { -- struct func *func = &traces[i].func; -- -- printf("%s%s(", -- value_to_str(traces[i].btf, &func->args[KSNOOP_RETURN], -- str), -- func->name); -- for (j = 0; j < func->nr_args; j++) { -- if (j > 0) -- printf(", "); -- printf("%s", value_to_str(traces[i].btf, &func->args[j], -- str)); -- } -- if (func->nr_args > MAX_ARGS) -- printf(" /* and %d more args that are not traceable */", -- func->nr_args - MAX_ARGS); -- printf(");\n"); -- } -- free(traces); -- return 0; --} -- --static void trace_handler(void *ctx, int cpu, void *data, __u32 size) --{ -- struct trace *trace = data; -- int i, shown, ret; -- -- p_debug("got trace, size %d", size); -- if (size < (sizeof(*trace) - MAX_TRACE_BUF)) { -- p_err("\t/* trace buffer size '%u' < min %ld */", -- size, sizeof(trace) - MAX_TRACE_BUF); -- return; -- } -- printf("%16lld %4d %8u %s(\n", trace->time, trace->cpu, trace->pid, -- trace->func.name); -- -- for (i = 0, shown = 0; i < trace->nr_traces; i++) { -- DECLARE_LIBBPF_OPTS(btf_dump_type_data_opts, opts); -- bool entry = trace->data_flags & KSNOOP_F_ENTRY; -- struct value *val = &trace->traces[i]; -- struct trace_data *data = &trace->trace_data[i]; -- -- opts.indent_level = 36; -- opts.indent_str = " "; -- -- /* skip if it's entry data and trace data is for return, or -- * if it's return and trace data is entry; only exception in -- * the latter case is if we stashed data; in such cases we -- * want to see it as it's a mix of entry/return data with -- * predicates. -- */ -- if ((entry && !base_arg_is_entry(val->base_arg)) || -- (!entry && base_arg_is_entry(val->base_arg) && -- !(trace->flags & KSNOOP_F_STASH))) -- continue; -- -- if (val->type_id == 0) -- continue; -- -- if (shown > 0) -- printf(",\n"); -- printf("%34s %s = ", "", val->name); -- if (val->flags & KSNOOP_F_PTR) -- printf("*(0x%llx)", data->raw_value); -- printf("\n"); -- -- if (data->err_type_id != 0) { -- char typestr[MAX_STR]; -- -- printf("%36s /* Cannot show '%s' as '%s%s'; invalid/userspace ptr? */\n", -- "", -- val->name, -- type_id_to_str(trace->btf, -- val->type_id, -- typestr), -- val->flags & KSNOOP_F_PTR ? -- " *" : ""); -- } else { -- ret = btf_dump__dump_type_data -- (trace->dump, val->type_id, -- trace->buf + data->buf_offset, -- data->buf_len, &opts); -- /* truncated? */ -- if (ret == -E2BIG) -- printf("%36s... /* %d bytes of %d */", "", -- data->buf_len, -- val->size); -- } -- shown++; -- -- } -- printf("\n%31s);\n\n", ""); -- fflush(stdout); --} -- --static void lost_handler(void *ctx, int cpu, __u64 cnt) --{ -- p_err("\t/* lost %llu events */", cnt); --} -- --static void sig_int(int signo) --{ -- exiting = 1; --} -- --static int add_traces(struct bpf_map *func_map, struct trace *traces, -- int nr_traces) --{ -- int i, j, ret, nr_cpus = libbpf_num_possible_cpus(); -- struct trace *map_traces; -- -- map_traces = calloc(nr_cpus, sizeof(struct trace)); -- if (!map_traces) { -- p_err("Could not allocate memory for %d traces", nr_traces); -- return -ENOMEM; -- } -- for (i = 0; i < nr_traces; i++) { -- for (j = 0; j < nr_cpus; j++) -- memcpy(&map_traces[j], &traces[i], -- sizeof(map_traces[j])); -- -- ret = bpf_map_update_elem(bpf_map__fd(func_map), -- &traces[i].func.ip, -- map_traces, -- BPF_NOEXIST); -- if (ret) { -- p_err("Could not add map entry for '%s': %s", -- traces[i].func.name, strerror(-ret)); -- break; -- } -- } -- free(map_traces); -- return ret; --} -- --static int attach_traces(struct ksnoop_bpf *skel, struct trace *traces, -- int nr_traces) --{ -- int i, ret; -- -- for (i = 0; i < nr_traces; i++) { -- traces[i].links[0] = -- bpf_program__attach_kprobe(skel->progs.kprobe_entry, -- false, -- traces[i].func.name); -- ret = libbpf_get_error(traces[i].links[0]); -- if (ret) { -- p_err("Could not attach kprobe to '%s': %s", -- traces[i].func.name, strerror(-ret)); -- return ret; -- } -- p_debug("Attached kprobe for '%s'", traces[i].func.name); -- -- traces[i].links[1] = -- bpf_program__attach_kprobe(skel->progs.kprobe_return, -- true, -- traces[i].func.name); -- ret = libbpf_get_error(traces[i].links[1]); -- if (ret) { -- p_err("Could not attach kretprobe to '%s': %s", -- traces[i].func.name, strerror(-ret)); -- return ret; -- } -- p_debug("Attached kretprobe for '%s'", traces[i].func.name); -- } -- return 0; --} -- --static int cmd_trace(int argc, char **argv) --{ -- struct perf_buffer_opts pb_opts = {}; -- struct bpf_map *perf_map, *func_map; -- struct perf_buffer *pb = NULL; -- struct ksnoop_bpf *skel; -- int i, nr_traces, ret = -1; -- struct trace *traces = NULL; -- -- nr_traces = parse_traces(argc, argv, &traces); -- if (nr_traces < 0) -- return nr_traces; -- -- skel = ksnoop_bpf__open_and_load(); -- if (!skel) { -- p_err("Could not load ksnoop BPF: %s", libbpf_errstr(skel)); -- return 1; -- } -- -- perf_map = skel->maps.ksnoop_perf_map; -- if (!perf_map) { -- p_err("Could not find '%s'", "ksnoop_perf_map"); -- goto cleanup; -- } -- func_map = bpf_object__find_map_by_name(skel->obj, "ksnoop_func_map"); -- if (!func_map) { -- p_err("Could not find '%s'", "ksnoop_func_map"); -- goto cleanup; -- } -- -- if (add_traces(func_map, traces, nr_traces)) { -- p_err("Could not add traces to '%s'", "ksnoop_func_map"); -- goto cleanup; -- } -- -- if (attach_traces(skel, traces, nr_traces)) { -- p_err("Could not attach %d traces", nr_traces); -- goto cleanup; -- } -- -- pb_opts.sample_cb = trace_handler; -- pb_opts.lost_cb = lost_handler; -- pb = perf_buffer__new(bpf_map__fd(perf_map), pages, &pb_opts); -- if (libbpf_get_error(pb)) { -- p_err("Could not create perf buffer: %s", -- libbpf_errstr(pb)); -- goto cleanup; -- } -- -- printf("%16s %4s %8s %s\n", "TIME", "CPU", "PID", "FUNCTION/ARGS"); -- -- if (signal(SIGINT, sig_int) == SIG_ERR) { -- fprintf(stderr, "can't set signal handler: %s\n", strerror(errno)); -- ret = 1; -- goto cleanup; -- } -- -- while (!exiting) { -- ret = perf_buffer__poll(pb, 1); -- if (ret < 0 && errno != EINTR) { -- fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno)); -- goto cleanup; -- } -- /* reset ret to return 0 if exiting */ -- ret = 0; -- } -- --cleanup: -- for (i = 0; i < nr_traces; i++) { -- bpf_link__destroy(traces[i].links[0]); -- bpf_link__destroy(traces[i].links[1]); -- } -- free(traces); -- perf_buffer__free(pb); -- ksnoop_bpf__destroy(skel); -- -- return ret; --} -- --struct cmd { -- const char *cmd; -- int (*func)(int argc, char **argv); --}; -- --struct cmd cmds[] = { -- { "info", cmd_info }, -- { "trace", cmd_trace }, -- { "help", cmd_help }, -- { NULL, NULL } --}; -- --static int cmd_select(int argc, char **argv) --{ -- int i; -- -- for (i = 0; cmds[i].cmd; i++) { -- if (strncmp(*argv, cmds[i].cmd, strlen(*argv)) == 0) -- return cmds[i].func(argc - 1, argv + 1); -- } -- return cmd_trace(argc, argv); --} -- --static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) --{ -- if (level == LIBBPF_DEBUG && !verbose) -- return 0; -- return vfprintf(stderr, format, args); --} -- --int main(int argc, char *argv[]) --{ -- static const struct option options[] = { -- { "debug", no_argument, NULL, 'd' }, -- { "verbose", no_argument, NULL, 'v' }, -- { "help", no_argument, NULL, 'h' }, -- { "version", no_argument, NULL, 'V' }, -- { "pages", required_argument, NULL, 'P' }, -- { "pid", required_argument, NULL, 'p' }, -- { 0 } -- }; -- int opt; -- -- bin_name = argv[0]; -- -- while ((opt = getopt_long(argc, argv, "dvhp:P:sV", options, -- NULL)) >= 0) { -- switch (opt) { -- case 'd': -- verbose = true; -- log_level = DEBUG; -- break; -- case 'v': -- verbose = true; -- log_level = DEBUG; -- break; -- case 'h': -- return cmd_help(argc, argv); -- case 'V': -- return do_version(argc, argv); -- case 'p': -- filter_pid = atoi(optarg); -- break; -- case 'P': -- pages = atoi(optarg); -- break; -- case 's': -- stack_mode = true; -- break; -- default: -- p_err("unrecognized option '%s'", argv[optind - 1]); -- usage(); -- } -- } -- if (argc == 1) -- usage(); -- argc -= optind; -- argv += optind; -- if (argc < 0) -- usage(); -- -- libbpf_set_print(libbpf_print_fn); -- -- return cmd_select(argc, argv); --} -diff --git a/libbpf-tools/ksnoop.h b/libbpf-tools/ksnoop.h -deleted file mode 100644 -index 6b33df4e..00000000 ---- a/libbpf-tools/ksnoop.h -+++ /dev/null -@@ -1,123 +0,0 @@ --/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ --/* Copyright (c) 2021, Oracle and/or its affiliates. */ -- --/* maximum number of different functions we can trace at once */ --#define MAX_FUNC_TRACES 64 -- --enum arg { -- KSNOOP_ARG1, -- KSNOOP_ARG2, -- KSNOOP_ARG3, -- KSNOOP_ARG4, -- KSNOOP_ARG5, -- KSNOOP_RETURN --}; -- --/* we choose "return" as the name for the returned value because as -- * a C keyword it can't clash with a function entry parameter. -- */ --#define KSNOOP_RETURN_NAME "return" -- --/* if we can't get a type id for a type (such as module-specific type) -- * mark it as KSNOOP_ID_UNKNOWN since BTF lookup in bpf_snprintf_btf() -- * will fail and the data will be simply displayed as a __u64. -- */ --#define KSNOOP_ID_UNKNOWN 0xffffffff -- --#define MAX_NAME 96 --#define MAX_STR 256 --#define MAX_PATH 512 --#define MAX_VALUES 6 --#define MAX_ARGS (MAX_VALUES - 1) --#define KSNOOP_F_PTR 0x1 /* value is a pointer */ --#define KSNOOP_F_MEMBER 0x2 /* member reference */ --#define KSNOOP_F_ENTRY 0x4 --#define KSNOOP_F_RETURN 0x8 --#define KSNOOP_F_CUSTOM 0x10 /* custom trace */ --#define KSNOOP_F_STASH 0x20 /* store values on entry, -- * no perf events. -- */ --#define KSNOOP_F_STASHED 0x40 /* values stored on entry */ -- --#define KSNOOP_F_PREDICATE_EQ 0x100 --#define KSNOOP_F_PREDICATE_NOTEQ 0x200 --#define KSNOOP_F_PREDICATE_GT 0x400 --#define KSNOOP_F_PREDICATE_LT 0x800 -- --#define KSNOOP_F_PREDICATE_MASK (KSNOOP_F_PREDICATE_EQ | \ -- KSNOOP_F_PREDICATE_NOTEQ | \ -- KSNOOP_F_PREDICATE_GT | \ -- KSNOOP_F_PREDICATE_LT) -- --/* for kprobes, entry is function IP + sizeof(kprobe_opcode_t), -- * subtract in BPF prog context to get fn address. -- */ --#ifdef __TARGET_ARCH_x86 --#define KSNOOP_IP_FIX(ip) (ip - sizeof(kprobe_opcode_t)) --#else --#define KSNOOP_IP_FIX(ip) ip --#endif -- --struct value { -- char name[MAX_STR]; -- enum arg base_arg; -- __u32 offset; -- __u32 size; -- __u64 type_id; -- __u64 flags; -- __u64 predicate_value; --}; -- --struct func { -- char name[MAX_NAME]; -- char mod[MAX_NAME]; -- __s32 id; -- __u8 nr_args; -- __u64 ip; -- struct value args[MAX_VALUES]; --}; -- --#define MAX_TRACES MAX_VALUES -- --#define MAX_TRACE_DATA 2048 -- --struct trace_data { -- __u64 raw_value; -- __u32 err_type_id; /* type id we can't dereference */ -- int err; -- __u32 buf_offset; -- __u16 buf_len; --}; -- --#define MAX_TRACE_BUF (MAX_TRACES * MAX_TRACE_DATA) -- --struct trace { -- /* initial values are readonly in tracing context */ -- struct btf *btf; -- struct btf_dump *dump; -- struct func func; -- __u8 nr_traces; -- __u32 filter_pid; -- __u64 prev_ip; /* these are used in stack-mode tracing */ -- __u64 next_ip; -- struct value traces[MAX_TRACES]; -- __u64 flags; -- /* values below this point are set or modified in tracing context */ -- __u64 task; -- __u32 pid; -- __u32 cpu; -- __u64 time; -- __u64 data_flags; -- struct trace_data trace_data[MAX_TRACES]; -- __u16 buf_len; -- char buf[MAX_TRACE_BUF]; -- char buf_end[0]; -- struct bpf_link *links[2]; --}; -- --#define PAGES_DEFAULT 16 -- --static inline int base_arg_is_entry(enum arg base_arg) --{ -- return base_arg != KSNOOP_RETURN; --} -diff --git a/man/man8/ksnoop.8 b/man/man8/ksnoop.8 -deleted file mode 100644 -index 8733cb73..00000000 ---- a/man/man8/ksnoop.8 -+++ /dev/null -@@ -1,298 +0,0 @@ --.\" Man page generated from reStructuredText. --. --.TH KSNOOP 8 "" "" "" --.SH NAME --KSNOOP \- tool for tracing kernel function entry/return showing arguments/return values --. --.nr rst2man-indent-level 0 --. --.de1 rstReportMargin --\\$1 \\n[an-margin] --level \\n[rst2man-indent-level] --level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] --- --\\n[rst2man-indent0] --\\n[rst2man-indent1] --\\n[rst2man-indent2] --.. --.de1 INDENT --.\" .rstReportMargin pre: --. RS \\$1 --. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] --. nr rst2man-indent-level +1 --.\" .rstReportMargin post: --.. --.de UNINDENT --. RE --.\" indent \\n[an-margin] --.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] --.nr rst2man-indent-level -1 --.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] --.in \\n[rst2man-indent\\n[rst2man-indent-level]]u --.. --.SH SYNOPSIS --.INDENT 0.0 --.INDENT 3.5 --\fBksnoop\fP [\fIOPTIONS\fP] { \fICOMMAND\fP \fIFUNC\fP | \fBhelp\fP } --.sp --\fIOPTIONS\fP := { { \fB\-V\fP | \fB\-\-version\fP } | { \fB\-h\fP | \fB\-\-help\fP } --| { [\fB\-P\fP | \fB\-\-pages\fP] nr_pages} | { [\fB\-p\fP | \fB\-\-pid\fP] pid} | --[{ \fB\-s\fP | \fB\-\-stack\fP }] | [{ \fB\-d\fP | \fB\-\-debug\fP }] } --.sp --\fICOMMAND\fP := { \fBtrace\fP | \fBinfo\fP } --.sp --\fIFUNC\fP := { \fBname\fP | \fBname\fP(\fBarg\fP[,**arg]) } --.UNINDENT --.UNINDENT --.SH DESCRIPTION --.INDENT 0.0 --.INDENT 3.5 --\fIksnoop\fP allows for inspection of arguments and return values --associated with function entry/return. --.INDENT 0.0 --.TP --.B \fBksnoop info\fP \fIFUNC\fP --Show function description, arguments and return value types. --.TP --.B \fBksnoop trace\fP \fIFUNC\fP [\fIFUNC\fP] --Trace function entry and return, showing arguments and --return values. A function name can simply be specified, --or a function name along with named arguments, return values. --\fBreturn\fP is used to specify the return value. --.UNINDENT --.sp --\fIksnoop\fP requires the kernel to provide BTF for itself, and if --tracing of module data is required, module BTF must be present also. --Check /sys/kernel/btf to see if BTF is present. --.sp --\fBksnoop\fP requires \fICAP_BPF\fP and \fICAP_TRACING\fP capabilities. --.UNINDENT --.UNINDENT --.SH OPTIONS --.INDENT 0.0 --.INDENT 3.5 --.INDENT 0.0 --.TP --.B \-h\fP,\fB \-\-help --Show help information --.TP --.B \-V\fP,\fB \-\-version --Show version. --.TP --.B \-d\fP,\fB \-\-debug --Show debug output. --.TP --.B \-p\fP,\fB \-\-pid --Filter events by pid. --.TP --.B \-P\fP,\fB \-\-pages --Specify number of pages used per\-CPU for perf event --collection. Default is 8. --.TP --.B \-s\fP,\fB \-\-stack --Specified set of functions are traced if and only --if they are encountered in the order specified. --.UNINDENT --.UNINDENT --.UNINDENT --.SH EXAMPLES --.sp --\fB# ksnoop info ip_send_skb\fP --.INDENT 0.0 --.INDENT 3.5 --.sp --.nf --.ft C --int ip_send_skb(struct net * net, struct sk_buff * skb); --.ft P --.fi --.UNINDENT --.UNINDENT --.sp --Show function description. --.sp --\fB# ksnoop trace ip_send_skb\fP --.INDENT 0.0 --.INDENT 3.5 --.sp --.nf --.ft C -- TIME CPU PID FUNCTION/ARGS --78101668506811 1 2813 ip_send_skb( -- net = *(0xffffffffb5959840) -- (struct net){ -- .passive = (refcount_t){ -- .refs = (atomic_t){ -- .counter = (int)0x2, -- }, -- }, -- .dev_base_seq = (unsigned int)0x18, -- .ifindex = (int)0xf, -- .list = (struct list_head){ -- .next = (struct list_head *)0xffff9895440dc120, -- .prev = (struct list_head *)0xffffffffb595a8d0, -- }, -- ... -- --79561322965250 1 2813 ip_send_skb( -- return = -- (int)0x0 -- ); --.ft P --.fi --.UNINDENT --.UNINDENT --.sp --Show entry/return for ip_send_skb() with arguments, return values. --.sp --\fB# ksnoop trace "ip_send_skb(skb)"\fP --.INDENT 0.0 --.INDENT 3.5 --.sp --.nf --.ft C -- TIME CPU PID FUNCTION/ARGS --78142420834537 1 2813 ip_send_skb( -- skb = *(0xffff989750797c00) -- (struct sk_buff){ -- (union){ -- .sk = (struct sock *)0xffff98966ce19200, -- .ip_defrag_offset = (int)0x6ce19200, -- }, -- (union){ -- (struct){ -- ._skb_refdst = (long unsigned int)0xffff98981dde2d80, -- .destructor = (void (*)(struct sk_buff *))0xffffffffb3e1beb0, -- }, -- ... --.ft P --.fi --.UNINDENT --.UNINDENT --.sp --Show entry argument \fBskb\fP\&. --.sp --\fB# ksnoop trace "ip_send_skb(return)"\fP --.INDENT 0.0 --.INDENT 3.5 --.sp --.nf --.ft C -- TIME CPU PID FUNCTION/ARGS --78178228354796 1 2813 ip_send_skb( -- return = -- (int)0x0 -- ); --.ft P --.fi --.UNINDENT --.UNINDENT --.sp --Show return value from ip_send_skb(). --.sp --\fB# ksnoop trace "ip_send_skb(skb\->sk)"\fP --.INDENT 0.0 --.INDENT 3.5 --.sp --.nf --.ft C -- TIME CPU PID FUNCTION/ARGS --78207649138829 2 2813 ip_send_skb( -- skb\->sk = *(0xffff98966ce19200) -- (struct sock){ -- .__sk_common = (struct sock_common){ -- (union){ -- .skc_addrpair = (__addrpair)0x1701a8c017d38f8d, -- (struct){ -- .skc_daddr = (__be32)0x17d38f8d, -- .skc_rcv_saddr = (__be32)0x1701a8c0, -- }, -- }, -- ... --.ft P --.fi --.UNINDENT --.UNINDENT --.sp --Trace member information associated with argument. Only one level of --membership is supported. --.sp --\fB# ksnoop \-p 2813 "ip_rcv(dev)"\fP --.INDENT 0.0 --.INDENT 3.5 --.sp --.nf --.ft C -- TIME CPU PID FUNCTION/ARGS --78254803164920 1 2813 ip_rcv( -- dev = *(0xffff9895414cb000) -- (struct net_device){ -- .name = (char[16])[ -- \(aql\(aq, -- \(aqo\(aq, -- ], -- .name_node = (struct netdev_name_node *)0xffff989541515ec0, -- .state = (long unsigned int)0x3, -- ... --.ft P --.fi --.UNINDENT --.UNINDENT --.sp --Trace \fBdev\fP argument of \fBip_rcv()\fP\&. Specify process id 2813 for events --for that process only. --.sp --\fB# ksnoop \-s tcp_sendmsg __tcp_transmit_skb ip_output\fP --.INDENT 0.0 --.INDENT 3.5 --.sp --.nf --.ft C -- TIME CPU PID FUNCTION/ARGS --71827770952903 1 4777 __tcp_transmit_skb( -- sk = *(0xffff9852460a2300) -- (struct sock){ -- .__sk_common = (struct sock_common){ -- (union){ -- .skc_addrpair = (__addrpair)0x61b2af0a35cbfe0a, --.ft P --.fi --.UNINDENT --.UNINDENT --.sp --Trace entry/return of tcp_sendmsg, __tcp_transmit_skb and ip_output when --tcp_sendmsg leads to a call to __tcp_transmit_skb and that in turn --leads to a call to ip_output; i.e. with a call graph matching the order --specified. The order does not have to be direct calls, i.e. function A --can call another function that calls function B. --.sp --\fB# ksnoop "ip_send_skb(skb\->len > 100, skb)"\fP --.INDENT 0.0 --.INDENT 3.5 --.sp --.nf --.ft C -- TIME CPU PID FUNCTION/ARGS --39267395709745 1 2955 ip_send_skb( -- skb\->len = -- (unsigned int)0x89, -- skb = *(0xffff89c8be81e500) -- (struct sk_buff){ -- (union){ -- .sk = (struct sock *)0xffff89c6c59e5580, -- .ip_defrag_offset = (int)0xc59e5580, -- }, --.ft P --.fi --.UNINDENT --.UNINDENT --.sp --Trace ip_send_skb() skbs which have len > 100. --.SH SEE ALSO --.INDENT 0.0 --.INDENT 3.5 --\fBbpf\fP(2), --.UNINDENT --.UNINDENT --.\" Generated by docutils manpage writer. --. --- -2.35.1 - diff --git a/bcc-0.24.0-Revert-libbpf-1.0-changes.patch b/bcc-0.24.0-Revert-libbpf-1.0-changes.patch deleted file mode 100644 index 8d86dd9..0000000 --- a/bcc-0.24.0-Revert-libbpf-1.0-changes.patch +++ /dev/null @@ -1,2331 +0,0 @@ -From 09cee55c78fe5c165c7d7c21f596c23831f844e1 Mon Sep 17 00:00:00 2001 -From: Jerome Marchand -Date: Tue, 19 Apr 2022 18:02:13 +0200 -Subject: [PATCH] Revert libbpf 1.0 changes - -Revert "libbpf-tools: remove now unnecessary bump_memlock_rlimit()" - -This reverts commit 5d8f5c45b16c389bb342d2b80c9f5e13e4f3b112. - -Revert "libbpf-tools: update vfsstat for libbpf 1.0" - -This reverts commit f083d3dc37372e555133519cb417f893c431eef0. - -Revert "libbpf-tools: update tcprtt for libbpf 1.0" - -This reverts commit a5b6c3cb2d20718ef002e7447046fad877590b91. - -Revert "libbpf-tools: update tcpconnlat for libbpf 1.0" - -This reverts commit aae06012af8cc8c2b592340f8783a2873aad2023. - -Revert "libbpf-tools: update tcpconnect for libbpf 1.0" - -This reverts commit 4051a9e83cb68733af20ce263fcc41c8aadc2622. - -Revert "libbpf-tools: update syscount for libbpf 1.0" - -This reverts commit d2dc7bcd0d94ef54e336119a2a79113b87839820. - -Revert "libbpf-tools: update statsnoop for libbpf 1.0" - -This reverts commit 0e348e5ed66aabd0cd5c0c75932f245bd1385b3b. - -Revert "libbpf-tools: update solisten for libbpf 1.0" - -This reverts commit 60dd074e26e762727e685334999bec5851adaef9. - -Revert "libbpf-tools: update softirqs for libbpf 1.0" - -This reverts commit 92806a435c2e1b248acdb9d0dc5b3eedc86994b0. - -Revert "libbpf-tools: update runqslower for libbpf 1.0" - -This reverts commit e6477620ccfc9abe10f7e630e65381204daa5ba8. - -Revert "libbpf-tools: update runqlen for libbpf 1.0" - -This reverts commit a7f0148372018140940d66f8faf53cb5add1e858. - -Revert "libbpf-tools: update runqlat for libbpf 1.0" - -This reverts commit 865f990b7139dca166a43bbc8159f6acd4bfbee6. - -Revert "libbpf-tools: update readahead for libbpf 1.0" - -This reverts commit 3c5dae6380dcc2034a8746c648e3bb24ea61f886. - -Revert "libbpf-tools: update opensnoop for libbpf 1.0" - -This reverts commit 34a680ba8da7e61befad67ebccb69c5041e9e288. - -Revert "libbpf-tools: update offcputime for libbpf 1.0" - -This reverts commit 5ef6d9922841d7cfde1994c25ccbac53858ed99f. - -Revert "libbpf-tools: update numamove for libbpf 1.0" - -This reverts commit 824ffd2a1fbb527f5fd25e2caa4b43fbf1ee858b. - -Revert "libbpf-tools: update mountsnoop for libbpf 1.0" - -This reverts commit 08301e93e5cea8575d5dc4b66fb7a76cebd5969b. - -Revert "libbpf-tools: update llcstat for libbpf 1.0" - -This reverts commit dbee9ea8ede33166fa70ecc33af7d7721ef26280. - -Revert "libbpf-tools: update hardirqs for libbpf 1.0" - -This reverts commit 8fcf08c81d30d80f89f995f79ef3246ce99c72dd. - -Revert "libbpf-tools: update gethostlatency for libbpf 1.0" - -This reverts commit 54a239abd21df9d6fc5d8db7ae7a26c5d8db2440. - -Revert "libbpf-tools: update funclatency for libbpf 1.0" - -This reverts commit d7b3ed3a8b2169087534738670d108489711f2d1. - -Revert "libbpf-tools: update fsslower for libbpf 1.0" - -This reverts commit 511ab72f046848d6df3f7c6ec0411b1609e165fb. - -Revert "libbpf-tools: update fsdist for libbpf 1.0" - -This reverts commit 21586658c86e1a20e9195d8715d37d714be93bb6. - -Revert "libbpf-tools: update filetop for libbpf 1.0" - -This reverts commit e6d151227f56433a317790d56ba7875ccae00448. - -Revert "libbpf-tools: update filelife for libbpf 1.0" - -This reverts commit 4ca8dd95efb7c4f149b889b700beeda036ebe822. - -Revert "libbpf-tools: update exitsnoop for libbpf 1.0" - -This reverts commit 0a035be644cf818354f3faab25a74e005a66d954. - -Revert "libbpf-tools: update execsnoop for libbpf 1.0" - -This reverts commit 7da38aabbefa41b8553e9fdec7744a5e423b5119. - -Revert "libbpf-tools: update cpudist for libbpf 1.0" - -This reverts commit dab1d09ef49e74c4c95f933e97e16dfc074338c2. - -Revert "libbpf-tools: update drsnoop for libbpf 1.0" - -This reverts commit 9cfdf5e04b32ca079a634ff60de7c08e3c41ccf5. - -Revert "libbpf-tools: fix cpufreq.bpf.c and update cpufreq for libbpf 1.0" - -This reverts commit f2006eaa5901d6ccf51d24b18c644f2fb1d41757. - -Revert "libbpf-tools: update cachestat for libbpf 1.0" - -This reverts commit 4970d23f9ff308c5860612ad6395d7692b05104e. - -Revert "libbpf-tools: update bitesize for libbpf 1.0" - -This reverts commit 7bea6c4ad9a460fc34eb618e488e44ca014e8ac7. - -Revert "libbpf-tools: update biostacks for libbpf 1.0" - -This reverts commit 49bb367628500104411d42851194162bec5d1f4c. - -Revert "libbpf-tools: update biosnoop for libbpf 1.0" - -This reverts commit 519ed8cf9c0daff75ecb3f435a3efec2087945a6. - -Revert "libbpf-tools: update biopattern for libbpf 1.0" - -This reverts commit c5b17e65a6e59fae1223bf493648050643ad9179. - -Revert "libbpf-tools: update biolatency for libbpf 1.0" - -This reverts commit 24d723699fbeeb8686acabc09ecefcceb749b9e0. - -Revert "libbpf-tools: update bindsnoop for libbpf 1.0" - -This reverts commit 7f2f4c4123a55438754b1a29f7ad3d3cfdbc7373. - -Revert "libbpf-tools: update ksnoop for libbpf 1.0" - -This reverts commit 18dc2ac7d84a854e2f5ac9ce1b532a0c59acf49e. - -Revert "libbpf-tools: update bashreadline for libbpf 1.0" - -This reverts commit 2cf0ba491d16386529c50ff0a9ec3eb9f86a2493. - -Signed-off-by: Jerome Marchand ---- - libbpf-tools/bashreadline.c | 24 ++++++++----- - libbpf-tools/bindsnoop.c | 21 +++++++---- - libbpf-tools/biolatency.c | 28 +++++++++------ - libbpf-tools/biopattern.c | 7 +++- - libbpf-tools/biosnoop.c | 67 +++++++++++++++++++++-------------- - libbpf-tools/biostacks.c | 39 ++++++++++++-------- - libbpf-tools/bitesize.c | 7 +++- - libbpf-tools/cachestat.c | 7 +++- - libbpf-tools/cpudist.c | 7 +++- - libbpf-tools/cpufreq.bpf.c | 11 ------ - libbpf-tools/cpufreq.c | 15 +++++--- - libbpf-tools/drsnoop.c | 21 +++++++---- - libbpf-tools/execsnoop.c | 22 ++++++++---- - libbpf-tools/exitsnoop.c | 20 +++++++---- - libbpf-tools/filelife.c | 21 +++++++---- - libbpf-tools/filetop.c | 6 +++- - libbpf-tools/fsdist.c | 38 +++++++++++++------- - libbpf-tools/fsslower.c | 46 ++++++++++++++++-------- - libbpf-tools/funclatency.c | 32 ++++++++++------- - libbpf-tools/gethostlatency.c | 49 +++++++++++++++---------- - libbpf-tools/hardirqs.c | 34 +++++++++++------- - libbpf-tools/ksnoop.c | 65 ++++++++++++++++----------------- - libbpf-tools/llcstat.bpf.c | 4 +-- - libbpf-tools/llcstat.c | 13 +++++-- - libbpf-tools/mountsnoop.c | 20 +++++++---- - libbpf-tools/numamove.c | 16 ++++++--- - libbpf-tools/offcputime.c | 7 +++- - libbpf-tools/opensnoop.c | 21 +++++++---- - libbpf-tools/readahead.c | 7 +++- - libbpf-tools/runqlat.c | 7 +++- - libbpf-tools/runqlen.c | 13 +++++-- - libbpf-tools/runqslower.c | 22 ++++++++---- - libbpf-tools/softirqs.c | 7 +++- - libbpf-tools/solisten.c | 20 +++++++---- - libbpf-tools/statsnoop.c | 20 +++++++---- - libbpf-tools/syscount.c | 18 ++++++---- - libbpf-tools/tcpconnect.c | 25 ++++++++----- - libbpf-tools/tcpconnlat.c | 24 +++++++++---- - libbpf-tools/tcprtt.c | 7 +++- - libbpf-tools/trace_helpers.c | 22 ++++++++---- - libbpf-tools/trace_helpers.h | 1 + - libbpf-tools/vfsstat.c | 8 ++++- - 42 files changed, 576 insertions(+), 293 deletions(-) - -diff --git a/libbpf-tools/bashreadline.c b/libbpf-tools/bashreadline.c -index 2fcb2e2c..ab3b955e 100644 ---- a/libbpf-tools/bashreadline.c -+++ b/libbpf-tools/bashreadline.c -@@ -149,6 +149,7 @@ int main(int argc, char **argv) - .doc = argp_program_doc, - }; - struct bashreadline_bpf *obj = NULL; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - char *readline_so_path; - off_t func_off; -@@ -165,7 +166,11 @@ int main(int argc, char **argv) - return 1; - } - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); -+ err = bump_memlock_rlimit(); -+ if (err) { -+ warn("failed to increase rlimit: %d\n", err); -+ goto cleanup; -+ } - libbpf_set_print(libbpf_print_fn); - - obj = bashreadline_bpf__open_and_load(); -@@ -182,16 +187,17 @@ int main(int argc, char **argv) - - obj->links.printret = bpf_program__attach_uprobe(obj->progs.printret, true, -1, - readline_so_path, func_off); -- if (!obj->links.printret) { -- err = -errno; -+ err = libbpf_get_error(obj->links.printret); -+ if (err) { - warn("failed to attach readline: %d\n", err); - goto cleanup; - } - -- pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ pb_opts.sample_cb = handle_event; -+ pb_opts.lost_cb = handle_lost_events; -+ pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { - warn("failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -205,8 +211,8 @@ int main(int argc, char **argv) - printf("%-9s %-7s %s\n", "TIME", "PID", "COMMAND"); - while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); -- if (err < 0 && err != -EINTR) { -- warn("error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ warn("error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - err = 0; -diff --git a/libbpf-tools/bindsnoop.c b/libbpf-tools/bindsnoop.c -index 5d87d484..c75b57e0 100644 ---- a/libbpf-tools/bindsnoop.c -+++ b/libbpf-tools/bindsnoop.c -@@ -174,6 +174,7 @@ int main(int argc, char **argv) - .parser = parse_arg, - .doc = argp_program_doc, - }; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - struct bindsnoop_bpf *obj; - int err, port_map_fd; -@@ -184,7 +185,11 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); -+ err = bump_memlock_rlimit(); -+ if (err) { -+ warn("failed to increase rlimit: %d\n", err); -+ return 1; -+ } - libbpf_set_print(libbpf_print_fn); - - obj = bindsnoop_bpf__open(); -@@ -219,10 +224,12 @@ int main(int argc, char **argv) - goto cleanup; - } - -- pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ pb_opts.sample_cb = handle_event; -+ pb_opts.lost_cb = handle_lost_events; -+ pb = perf_buffer__new(bpf_map__fd(obj->maps.events), -+ PERF_BUFFER_PAGES, &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { - warn("failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -240,8 +247,8 @@ int main(int argc, char **argv) - - while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); -- if (err < 0 && err != -EINTR) { -- warn("error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ warn("error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - /* reset err to return 0 if exiting */ -diff --git a/libbpf-tools/biolatency.c b/libbpf-tools/biolatency.c -index 51afa509..f2cf5ffd 100644 ---- a/libbpf-tools/biolatency.c -+++ b/libbpf-tools/biolatency.c -@@ -255,9 +255,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = biolatency_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -@@ -308,22 +313,25 @@ int main(int argc, char **argv) - } - - if (env.queued) { -- obj->links.block_rq_insert = bpf_program__attach(obj->progs.block_rq_insert); -- if (!obj->links.block_rq_insert) { -- err = -errno; -+ obj->links.block_rq_insert = -+ bpf_program__attach(obj->progs.block_rq_insert); -+ err = libbpf_get_error(obj->links.block_rq_insert); -+ if (err) { - fprintf(stderr, "failed to attach: %s\n", strerror(-err)); - goto cleanup; - } - } -- obj->links.block_rq_issue = bpf_program__attach(obj->progs.block_rq_issue); -- if (!obj->links.block_rq_issue) { -- err = -errno; -+ obj->links.block_rq_issue = -+ bpf_program__attach(obj->progs.block_rq_issue); -+ err = libbpf_get_error(obj->links.block_rq_issue); -+ if (err) { - fprintf(stderr, "failed to attach: %s\n", strerror(-err)); - goto cleanup; - } -- obj->links.block_rq_complete = bpf_program__attach(obj->progs.block_rq_complete); -- if (!obj->links.block_rq_complete) { -- err = -errno; -+ obj->links.block_rq_complete = -+ bpf_program__attach(obj->progs.block_rq_complete); -+ err = libbpf_get_error(obj->links.block_rq_complete); -+ if (err) { - fprintf(stderr, "failed to attach: %s\n", strerror(-err)); - goto cleanup; - } -diff --git a/libbpf-tools/biopattern.c b/libbpf-tools/biopattern.c -index 92324702..2cc0d9a3 100644 ---- a/libbpf-tools/biopattern.c -+++ b/libbpf-tools/biopattern.c -@@ -172,9 +172,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = biopattern_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -diff --git a/libbpf-tools/biosnoop.c b/libbpf-tools/biosnoop.c -index f0f665a6..618af38e 100644 ---- a/libbpf-tools/biosnoop.c -+++ b/libbpf-tools/biosnoop.c -@@ -190,6 +190,7 @@ int main(int argc, char **argv) - .parser = parse_arg, - .doc = argp_program_doc, - }; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - struct ksyms *ksyms = NULL; - struct biosnoop_bpf *obj; -@@ -202,9 +203,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = biosnoop_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -@@ -251,55 +257,64 @@ int main(int argc, char **argv) - } - } - -- obj->links.blk_account_io_start = bpf_program__attach(obj->progs.blk_account_io_start); -- if (!obj->links.blk_account_io_start) { -- err = -errno; -+ obj->links.blk_account_io_start = -+ bpf_program__attach(obj->progs.blk_account_io_start); -+ err = libbpf_get_error(obj->links.blk_account_io_start); -+ if (err) { - fprintf(stderr, "failed to attach blk_account_io_start: %s\n", -- strerror(-err)); -+ strerror(err)); - goto cleanup; - } - ksyms = ksyms__load(); - if (!ksyms) { -- err = -ENOMEM; - fprintf(stderr, "failed to load kallsyms\n"); - goto cleanup; - } - if (ksyms__get_symbol(ksyms, "blk_account_io_merge_bio")) { - obj->links.blk_account_io_merge_bio = - bpf_program__attach(obj->progs.blk_account_io_merge_bio); -- if (!obj->links.blk_account_io_merge_bio) { -- err = -errno; -- fprintf(stderr, "failed to attach blk_account_io_merge_bio: %s\n", -- strerror(-err)); -+ err = libbpf_get_error(obj->links.blk_account_io_merge_bio); -+ if (err) { -+ fprintf(stderr, "failed to attach " -+ "blk_account_io_merge_bio: %s\n", -+ strerror(err)); - goto cleanup; - } - } - if (env.queued) { - obj->links.block_rq_insert = - bpf_program__attach(obj->progs.block_rq_insert); -- if (!obj->links.block_rq_insert) { -- err = -errno; -- fprintf(stderr, "failed to attach block_rq_insert: %s\n", strerror(-err)); -+ err = libbpf_get_error(obj->links.block_rq_insert); -+ if (err) { -+ fprintf(stderr, "failed to attach block_rq_insert: %s\n", -+ strerror(err)); - goto cleanup; - } - } -- obj->links.block_rq_issue = bpf_program__attach(obj->progs.block_rq_issue); -- if (!obj->links.block_rq_issue) { -- err = -errno; -- fprintf(stderr, "failed to attach block_rq_issue: %s\n", strerror(-err)); -+ obj->links.block_rq_issue = -+ bpf_program__attach(obj->progs.block_rq_issue); -+ err = libbpf_get_error(obj->links.block_rq_issue); -+ if (err) { -+ fprintf(stderr, "failed to attach block_rq_issue: %s\n", -+ strerror(err)); - goto cleanup; - } -- obj->links.block_rq_complete = bpf_program__attach(obj->progs.block_rq_complete); -- if (!obj->links.block_rq_complete) { -- err = -errno; -- fprintf(stderr, "failed to attach block_rq_complete: %s\n", strerror(-err)); -+ obj->links.block_rq_complete = -+ bpf_program__attach(obj->progs.block_rq_complete); -+ err = libbpf_get_error(obj->links.block_rq_complete); -+ if (err) { -+ fprintf(stderr, "failed to attach block_rq_complete: %s\n", -+ strerror(err)); - goto cleanup; - } - -+ pb_opts.sample_cb = handle_event; -+ pb_opts.lost_cb = handle_lost_events; - pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { -+ pb = NULL; - fprintf(stderr, "failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -323,8 +338,8 @@ int main(int argc, char **argv) - /* main: poll */ - while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); -- if (err < 0 && err != -EINTR) { -- fprintf(stderr, "error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - if (env.duration && get_ktime_ns() > time_end) -diff --git a/libbpf-tools/biostacks.c b/libbpf-tools/biostacks.c -index 260bc235..c98fd532 100644 ---- a/libbpf-tools/biostacks.c -+++ b/libbpf-tools/biostacks.c -@@ -145,9 +145,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = biostacks_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -@@ -179,10 +184,12 @@ int main(int argc, char **argv) - goto cleanup; - } - -- obj->links.blk_account_io_start = bpf_program__attach(obj->progs.blk_account_io_start); -- if (!obj->links.blk_account_io_start) { -- err = -errno; -- fprintf(stderr, "failed to attach blk_account_io_start: %s\n", strerror(-err)); -+ obj->links.blk_account_io_start = -+ bpf_program__attach(obj->progs.blk_account_io_start); -+ err = libbpf_get_error(obj->links.blk_account_io_start); -+ if (err) { -+ fprintf(stderr, "failed to attach blk_account_io_start: %s\n", -+ strerror(err)); - goto cleanup; - } - ksyms = ksyms__load(); -@@ -192,19 +199,23 @@ int main(int argc, char **argv) - } - if (ksyms__get_symbol(ksyms, "blk_account_io_merge_bio")) { - obj->links.blk_account_io_merge_bio = -- bpf_program__attach(obj->progs.blk_account_io_merge_bio); -- if (!obj->links.blk_account_io_merge_bio) { -- err = -errno; -- fprintf(stderr, "failed to attach blk_account_io_merge_bio: %s\n", -- strerror(-err)); -+ bpf_program__attach(obj-> -+ progs.blk_account_io_merge_bio); -+ err = libbpf_get_error(obj-> -+ links.blk_account_io_merge_bio); -+ if (err) { -+ fprintf(stderr, "failed to attach " -+ "blk_account_io_merge_bio: %s\n", -+ strerror(err)); - goto cleanup; - } - } -- obj->links.blk_account_io_done = bpf_program__attach(obj->progs.blk_account_io_done); -- if (!obj->links.blk_account_io_done) { -- err = -errno; -+ obj->links.blk_account_io_done = -+ bpf_program__attach(obj->progs.blk_account_io_done); -+ err = libbpf_get_error(obj->links.blk_account_io_done); -+ if (err) { - fprintf(stderr, "failed to attach blk_account_io_done: %s\n", -- strerror(-err)); -+ strerror(err)); - goto cleanup; - } - -diff --git a/libbpf-tools/bitesize.c b/libbpf-tools/bitesize.c -index 4c371508..41b1a7db 100644 ---- a/libbpf-tools/bitesize.c -+++ b/libbpf-tools/bitesize.c -@@ -167,9 +167,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = bitesize_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -diff --git a/libbpf-tools/cachestat.c b/libbpf-tools/cachestat.c -index 05785251..abc81878 100644 ---- a/libbpf-tools/cachestat.c -+++ b/libbpf-tools/cachestat.c -@@ -139,9 +139,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = cachestat_bpf__open_and_load(); - if (!obj) { - fprintf(stderr, "failed to open and/or load BPF object\n"); -diff --git a/libbpf-tools/cpudist.c b/libbpf-tools/cpudist.c -index f76d8a67..035100ea 100644 ---- a/libbpf-tools/cpudist.c -+++ b/libbpf-tools/cpudist.c -@@ -197,9 +197,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = cpudist_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -diff --git a/libbpf-tools/cpufreq.bpf.c b/libbpf-tools/cpufreq.bpf.c -index 88a1bd25..697620ba 100644 ---- a/libbpf-tools/cpufreq.bpf.c -+++ b/libbpf-tools/cpufreq.bpf.c -@@ -17,21 +17,11 @@ struct { - __type(value, struct hist); - } hists SEC(".maps"); - --#define clamp_umax(VAR, UMAX) \ -- asm volatile ( \ -- "if %0 <= %[max] goto +1\n" \ -- "%0 = %[max]\n" \ -- : "+r"(VAR) \ -- : [max]"i"(UMAX) \ -- ) -- - SEC("tp_btf/cpu_frequency") - int BPF_PROG(cpu_frequency, unsigned int state, unsigned int cpu_id) - { - if (cpu_id >= MAX_CPU_NR) - return 0; -- -- clamp_umax(cpu_id, MAX_CPU_NR - 1); - freqs_mhz[cpu_id] = state / 1000; - return 0; - } -@@ -46,7 +36,6 @@ int do_sample(struct bpf_perf_event_data *ctx) - - if (cpu >= MAX_CPU_NR) - return 0; -- clamp_umax(cpu, MAX_CPU_NR - 1); - freq_mhz = freqs_mhz[cpu]; - if (!freq_mhz) - return 0; -diff --git a/libbpf-tools/cpufreq.c b/libbpf-tools/cpufreq.c -index c5839560..65876587 100644 ---- a/libbpf-tools/cpufreq.c -+++ b/libbpf-tools/cpufreq.c -@@ -102,8 +102,10 @@ static int open_and_attach_perf_event(int freq, struct bpf_program *prog, - return -1; - } - links[i] = bpf_program__attach_perf_event(prog, fd); -- if (!links[i]) { -- fprintf(stderr, "failed to attach perf event on cpu: %d\n", i); -+ if (libbpf_get_error(links[i])) { -+ fprintf(stderr, "failed to attach perf event on cpu: " -+ "%d\n", i); -+ links[i] = NULL; - close(fd); - return -1; - } -@@ -173,7 +175,7 @@ static void print_linear_hists(struct bpf_map *hists, - - printf("\n"); - print_linear_hist(bss->syswide.slots, MAX_SLOTS, 0, HIST_STEP_SIZE, -- "syswide"); -+ "syswide"); - } - - int main(int argc, char **argv) -@@ -191,9 +193,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - nr_cpus = libbpf_num_possible_cpus(); - if (nr_cpus < 0) { - fprintf(stderr, "failed to get # of possible cpus: '%s'!\n", -diff --git a/libbpf-tools/drsnoop.c b/libbpf-tools/drsnoop.c -index 705db9a4..89285871 100644 ---- a/libbpf-tools/drsnoop.c -+++ b/libbpf-tools/drsnoop.c -@@ -146,6 +146,7 @@ int main(int argc, char **argv) - .parser = parse_arg, - .doc = argp_program_doc, - }; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - struct ksyms *ksyms = NULL; - const struct ksym *ksym; -@@ -157,9 +158,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = drsnoop_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -@@ -207,10 +213,13 @@ int main(int argc, char **argv) - printf(" %8s", "FREE(KB)"); - printf("\n"); - -+ pb_opts.sample_cb = handle_event; -+ pb_opts.lost_cb = handle_lost_events; - pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { -+ pb = NULL; - fprintf(stderr, "failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -228,8 +237,8 @@ int main(int argc, char **argv) - /* main: poll */ - while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); -- if (err < 0 && err != -EINTR) { -- fprintf(stderr, "error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - if (env.duration && get_ktime_ns() > time_end) -diff --git a/libbpf-tools/execsnoop.c b/libbpf-tools/execsnoop.c -index 38294816..1fd573da 100644 ---- a/libbpf-tools/execsnoop.c -+++ b/libbpf-tools/execsnoop.c -@@ -263,6 +263,7 @@ int main(int argc, char **argv) - .parser = parse_arg, - .doc = argp_program_doc, - }; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - struct execsnoop_bpf *obj; - int err; -@@ -271,9 +272,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = execsnoop_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -@@ -311,10 +317,12 @@ int main(int argc, char **argv) - printf("%-16s %-6s %-6s %3s %s\n", "PCOMM", "PID", "PPID", "RET", "ARGS"); - - /* setup event callbacks */ -- pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ pb_opts.sample_cb = handle_event; -+ pb_opts.lost_cb = handle_lost_events; -+ pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { -+ pb = NULL; - fprintf(stderr, "failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -328,8 +336,8 @@ int main(int argc, char **argv) - /* main: poll */ - while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); -- if (err < 0 && err != -EINTR) { -- fprintf(stderr, "error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - /* reset err to return 0 if exiting */ -diff --git a/libbpf-tools/exitsnoop.c b/libbpf-tools/exitsnoop.c -index bca9d4d3..410e00da 100644 ---- a/libbpf-tools/exitsnoop.c -+++ b/libbpf-tools/exitsnoop.c -@@ -152,6 +152,7 @@ int main(int argc, char **argv) - .parser = parse_arg, - .doc = argp_program_doc, - }; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - struct exitsnoop_bpf *obj; - int err; -@@ -160,7 +161,11 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); -+ err = bump_memlock_rlimit(); -+ if (err) { -+ warn("failed to increase rlimit: %d\n", err); -+ return 1; -+ } - libbpf_set_print(libbpf_print_fn); - - obj = exitsnoop_bpf__open(); -@@ -185,10 +190,11 @@ int main(int argc, char **argv) - goto cleanup; - } - -- pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ pb_opts.sample_cb = handle_event; -+ pb_opts.lost_cb = handle_lost_events; -+ pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { - warn("failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -206,8 +212,8 @@ int main(int argc, char **argv) - - while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); -- if (err < 0 && err != -EINTR) { -- warn("error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ warn("error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - /* reset err to return 0 if exiting */ -diff --git a/libbpf-tools/filelife.c b/libbpf-tools/filelife.c -index ba6b9440..1f94039e 100644 ---- a/libbpf-tools/filelife.c -+++ b/libbpf-tools/filelife.c -@@ -110,6 +110,7 @@ int main(int argc, char **argv) - .parser = parse_arg, - .doc = argp_program_doc, - }; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - struct filelife_bpf *obj; - int err; -@@ -118,9 +119,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = filelife_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -@@ -145,10 +151,13 @@ int main(int argc, char **argv) - printf("Tracing the lifespan of short-lived files ... Hit Ctrl-C to end.\n"); - printf("%-8s %-6s %-16s %-7s %s\n", "TIME", "PID", "COMM", "AGE(s)", "FILE"); - -+ pb_opts.sample_cb = handle_event; -+ pb_opts.lost_cb = handle_lost_events; - pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { -+ pb = NULL; - fprintf(stderr, "failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -161,8 +170,8 @@ int main(int argc, char **argv) - - while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); -- if (err < 0 && err != -EINTR) { -- fprintf(stderr, "error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - /* reset err to return 0 if exiting */ -diff --git a/libbpf-tools/filetop.c b/libbpf-tools/filetop.c -index 70240d85..f1f7ba96 100644 ---- a/libbpf-tools/filetop.c -+++ b/libbpf-tools/filetop.c -@@ -268,7 +268,11 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); -+ err = bump_memlock_rlimit(); -+ if (err) { -+ warn("failed to increase rlimit: %d\n", err); -+ return 1; -+ } - libbpf_set_print(libbpf_print_fn); - - obj = filetop_bpf__open(); -diff --git a/libbpf-tools/fsdist.c b/libbpf-tools/fsdist.c -index f411d162..782a0e6a 100644 ---- a/libbpf-tools/fsdist.c -+++ b/libbpf-tools/fsdist.c -@@ -299,44 +299,53 @@ static int attach_kprobes(struct fsdist_bpf *obj) - - /* READ */ - obj->links.file_read_entry = bpf_program__attach_kprobe(obj->progs.file_read_entry, false, cfg->op_funcs[READ]); -- if (!obj->links.file_read_entry) -+ err = libbpf_get_error(obj->links.file_read_entry); -+ if (err) - goto errout; - obj->links.file_read_exit = bpf_program__attach_kprobe(obj->progs.file_read_exit, true, cfg->op_funcs[READ]); -- if (!obj->links.file_read_exit) -+ err = libbpf_get_error(obj->links.file_read_exit); -+ if (err) - goto errout; - /* WRITE */ - obj->links.file_write_entry = bpf_program__attach_kprobe(obj->progs.file_write_entry, false, cfg->op_funcs[WRITE]); -- if (!obj->links.file_write_entry) -+ err = libbpf_get_error(obj->links.file_write_entry); -+ if (err) - goto errout; - obj->links.file_write_exit = bpf_program__attach_kprobe(obj->progs.file_write_exit, true, cfg->op_funcs[WRITE]); -- if (!obj->links.file_write_exit) -+ err = libbpf_get_error(obj->links.file_write_exit); -+ if (err) - goto errout; - /* OPEN */ - obj->links.file_open_entry = bpf_program__attach_kprobe(obj->progs.file_open_entry, false, cfg->op_funcs[OPEN]); -- if (!obj->links.file_open_entry) -+ err = libbpf_get_error(obj->links.file_open_entry); -+ if (err) - goto errout; - obj->links.file_open_exit = bpf_program__attach_kprobe(obj->progs.file_open_exit, true, cfg->op_funcs[OPEN]); -- if (!obj->links.file_open_exit) -+ err = libbpf_get_error(obj->links.file_open_exit); -+ if (err) - goto errout; - /* FSYNC */ - obj->links.file_sync_entry = bpf_program__attach_kprobe(obj->progs.file_sync_entry, false, cfg->op_funcs[FSYNC]); -- if (!obj->links.file_sync_entry) -+ err = libbpf_get_error(obj->links.file_sync_entry); -+ if (err) - goto errout; - obj->links.file_sync_exit = bpf_program__attach_kprobe(obj->progs.file_sync_exit, true, cfg->op_funcs[FSYNC]); -- if (!obj->links.file_sync_exit) -+ err = libbpf_get_error(obj->links.file_sync_exit); -+ if (err) - goto errout; - /* GETATTR */ - if (!cfg->op_funcs[GETATTR]) - return 0; - obj->links.getattr_entry = bpf_program__attach_kprobe(obj->progs.getattr_entry, false, cfg->op_funcs[GETATTR]); -- if (!obj->links.getattr_entry) -+ err = libbpf_get_error(obj->links.getattr_entry); -+ if (err) - goto errout; - obj->links.getattr_exit = bpf_program__attach_kprobe(obj->progs.getattr_exit, true, cfg->op_funcs[GETATTR]); -- if (!obj->links.getattr_exit) -+ err = libbpf_get_error(obj->links.getattr_exit); -+ if (err) - goto errout; - return 0; - errout: -- err = -errno; - warn("failed to attach kprobe: %ld\n", err); - return err; - } -@@ -364,9 +373,14 @@ int main(int argc, char **argv) - return 1; - } - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ warn("failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - skel = fsdist_bpf__open(); - if (!skel) { - warn("failed to open BPF object\n"); -diff --git a/libbpf-tools/fsslower.c b/libbpf-tools/fsslower.c -index e96c9efa..2975b493 100644 ---- a/libbpf-tools/fsslower.c -+++ b/libbpf-tools/fsslower.c -@@ -256,36 +256,43 @@ static int attach_kprobes(struct fsslower_bpf *obj) - - /* READ */ - obj->links.file_read_entry = bpf_program__attach_kprobe(obj->progs.file_read_entry, false, cfg->op_funcs[READ]); -- if (!obj->links.file_read_entry) -+ err = libbpf_get_error(obj->links.file_read_entry); -+ if (err) - goto errout; - obj->links.file_read_exit = bpf_program__attach_kprobe(obj->progs.file_read_exit, true, cfg->op_funcs[READ]); -- if (!obj->links.file_read_exit) -+ err = libbpf_get_error(obj->links.file_read_exit); -+ if (err) - goto errout; - /* WRITE */ - obj->links.file_write_entry = bpf_program__attach_kprobe(obj->progs.file_write_entry, false, cfg->op_funcs[WRITE]); -- if (!obj->links.file_write_entry) -+ err = libbpf_get_error(obj->links.file_write_entry); -+ if (err) - goto errout; - obj->links.file_write_exit = bpf_program__attach_kprobe(obj->progs.file_write_exit, true, cfg->op_funcs[WRITE]); -- if (!obj->links.file_write_exit) -+ err = libbpf_get_error(obj->links.file_write_exit); -+ if (err) - goto errout; - /* OPEN */ - obj->links.file_open_entry = bpf_program__attach_kprobe(obj->progs.file_open_entry, false, cfg->op_funcs[OPEN]); -- if (!obj->links.file_open_entry) -+ err = libbpf_get_error(obj->links.file_open_entry); -+ if (err) - goto errout; - obj->links.file_open_exit = bpf_program__attach_kprobe(obj->progs.file_open_exit, true, cfg->op_funcs[OPEN]); -- if (!obj->links.file_open_exit) -+ err = libbpf_get_error(obj->links.file_open_exit); -+ if (err) - goto errout; - /* FSYNC */ - obj->links.file_sync_entry = bpf_program__attach_kprobe(obj->progs.file_sync_entry, false, cfg->op_funcs[FSYNC]); -- if (!obj->links.file_sync_entry) -+ err = libbpf_get_error(obj->links.file_sync_entry); -+ if (err) - goto errout; - obj->links.file_sync_exit = bpf_program__attach_kprobe(obj->progs.file_sync_exit, true, cfg->op_funcs[FSYNC]); -- if (!obj->links.file_sync_exit) -+ err = libbpf_get_error(obj->links.file_sync_exit); -+ if (err) - goto errout; - return 0; - - errout: -- err = -errno; - warn("failed to attach kprobe: %ld\n", err); - return err; - } -@@ -354,6 +361,7 @@ int main(int argc, char **argv) - .parser = parse_arg, - .doc = argp_program_doc, - }; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - struct fsslower_bpf *skel; - __u64 time_end = 0; -@@ -369,9 +377,14 @@ int main(int argc, char **argv) - return 1; - } - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ warn("failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - skel = fsslower_bpf__open(); - if (!skel) { - warn("failed to open BPF object\n"); -@@ -415,10 +428,13 @@ int main(int argc, char **argv) - goto cleanup; - } - -+ pb_opts.sample_cb = handle_event; -+ pb_opts.lost_cb = handle_lost_events; - pb = perf_buffer__new(bpf_map__fd(skel->maps.events), PERF_BUFFER_PAGES, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { -+ pb = NULL; - warn("failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -437,8 +453,8 @@ int main(int argc, char **argv) - /* main: poll */ - while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); -- if (err < 0 && err != -EINTR) { -- fprintf(stderr, "error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - if (duration && get_ktime_ns() > time_end) -diff --git a/libbpf-tools/funclatency.c b/libbpf-tools/funclatency.c -index 3ea0fec3..b079292e 100644 ---- a/libbpf-tools/funclatency.c -+++ b/libbpf-tools/funclatency.c -@@ -185,18 +185,20 @@ static int attach_kprobes(struct funclatency_bpf *obj) - { - long err; - -- obj->links.dummy_kprobe = bpf_program__attach_kprobe(obj->progs.dummy_kprobe, false, -- env.funcname); -- if (!obj->links.dummy_kprobe) { -- err = -errno; -+ obj->links.dummy_kprobe = -+ bpf_program__attach_kprobe(obj->progs.dummy_kprobe, false, -+ env.funcname); -+ err = libbpf_get_error(obj->links.dummy_kprobe); -+ if (err) { - warn("failed to attach kprobe: %ld\n", err); - return -1; - } - -- obj->links.dummy_kretprobe = bpf_program__attach_kprobe(obj->progs.dummy_kretprobe, true, -- env.funcname); -- if (!obj->links.dummy_kretprobe) { -- err = -errno; -+ obj->links.dummy_kretprobe = -+ bpf_program__attach_kprobe(obj->progs.dummy_kretprobe, true, -+ env.funcname); -+ err = libbpf_get_error(obj->links.dummy_kretprobe); -+ if (err) { - warn("failed to attach kretprobe: %ld\n", err); - return -1; - } -@@ -237,8 +239,8 @@ static int attach_uprobes(struct funclatency_bpf *obj) - obj->links.dummy_kprobe = - bpf_program__attach_uprobe(obj->progs.dummy_kprobe, false, - env.pid ?: -1, bin_path, func_off); -- if (!obj->links.dummy_kprobe) { -- err = -errno; -+ err = libbpf_get_error(obj->links.dummy_kprobe); -+ if (err) { - warn("Failed to attach uprobe: %ld\n", err); - goto out_binary; - } -@@ -246,8 +248,8 @@ static int attach_uprobes(struct funclatency_bpf *obj) - obj->links.dummy_kretprobe = - bpf_program__attach_uprobe(obj->progs.dummy_kretprobe, true, - env.pid ?: -1, bin_path, func_off); -- if (!obj->links.dummy_kretprobe) { -- err = -errno; -+ err = libbpf_get_error(obj->links.dummy_kretprobe); -+ if (err) { - warn("Failed to attach uretprobe: %ld\n", err); - goto out_binary; - } -@@ -296,7 +298,11 @@ int main(int argc, char **argv) - - sigaction(SIGINT, &sigact, 0); - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); -+ err = bump_memlock_rlimit(); -+ if (err) { -+ warn("failed to increase rlimit: %d\n", err); -+ return 1; -+ } - libbpf_set_print(libbpf_print_fn); - - obj = funclatency_bpf__open(); -diff --git a/libbpf-tools/gethostlatency.c b/libbpf-tools/gethostlatency.c -index 9b3ebc28..12076e6a 100644 ---- a/libbpf-tools/gethostlatency.c -+++ b/libbpf-tools/gethostlatency.c -@@ -164,14 +164,16 @@ static int attach_uprobes(struct gethostlatency_bpf *obj, struct bpf_link *links - } - links[0] = bpf_program__attach_uprobe(obj->progs.handle_entry, false, - target_pid ?: -1, libc_path, func_off); -- if (!links[0]) { -- warn("failed to attach getaddrinfo: %d\n", -errno); -+ err = libbpf_get_error(links[0]); -+ if (err) { -+ warn("failed to attach getaddrinfo: %d\n", err); - return -1; - } - links[1] = bpf_program__attach_uprobe(obj->progs.handle_return, true, - target_pid ?: -1, libc_path, func_off); -- if (!links[1]) { -- warn("failed to attach getaddrinfo: %d\n", -errno); -+ err = libbpf_get_error(links[1]); -+ if (err) { -+ warn("failed to attach getaddrinfo: %d\n", err); - return -1; - } - -@@ -182,14 +184,16 @@ static int attach_uprobes(struct gethostlatency_bpf *obj, struct bpf_link *links - } - links[2] = bpf_program__attach_uprobe(obj->progs.handle_entry, false, - target_pid ?: -1, libc_path, func_off); -- if (!links[2]) { -- warn("failed to attach gethostbyname: %d\n", -errno); -+ err = libbpf_get_error(links[2]); -+ if (err) { -+ warn("failed to attach gethostbyname: %d\n", err); - return -1; - } - links[3] = bpf_program__attach_uprobe(obj->progs.handle_return, true, - target_pid ?: -1, libc_path, func_off); -- if (!links[3]) { -- warn("failed to attach gethostbyname: %d\n", -errno); -+ err = libbpf_get_error(links[3]); -+ if (err) { -+ warn("failed to attach gethostbyname: %d\n", err); - return -1; - } - -@@ -200,14 +204,16 @@ static int attach_uprobes(struct gethostlatency_bpf *obj, struct bpf_link *links - } - links[4] = bpf_program__attach_uprobe(obj->progs.handle_entry, false, - target_pid ?: -1, libc_path, func_off); -- if (!links[4]) { -- warn("failed to attach gethostbyname2: %d\n", -errno); -+ err = libbpf_get_error(links[4]); -+ if (err) { -+ warn("failed to attach gethostbyname2: %d\n", err); - return -1; - } - links[5] = bpf_program__attach_uprobe(obj->progs.handle_return, true, - target_pid ?: -1, libc_path, func_off); -- if (!links[5]) { -- warn("failed to attach gethostbyname2: %d\n", -errno); -+ err = libbpf_get_error(links[5]); -+ if (err) { -+ warn("failed to attach gethostbyname2: %d\n", err); - return -1; - } - -@@ -221,6 +227,7 @@ int main(int argc, char **argv) - .parser = parse_arg, - .doc = argp_program_doc, - }; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - struct bpf_link *links[6] = {}; - struct gethostlatency_bpf *obj; -@@ -230,7 +237,11 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); -+ err = bump_memlock_rlimit(); -+ if (err) { -+ warn("failed to increase rlimit: %d\n", err); -+ return 1; -+ } - libbpf_set_print(libbpf_print_fn); - - obj = gethostlatency_bpf__open(); -@@ -251,10 +262,12 @@ int main(int argc, char **argv) - if (err) - goto cleanup; - -+ pb_opts.sample_cb = handle_event; -+ pb_opts.lost_cb = handle_lost_events; - pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { - warn("failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -270,8 +283,8 @@ int main(int argc, char **argv) - - while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); -- if (err < 0 && err != -EINTR) { -- warn("error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ warn("error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - /* reset err to return 0 if exiting */ -diff --git a/libbpf-tools/hardirqs.c b/libbpf-tools/hardirqs.c -index a2475ef1..759b3949 100644 ---- a/libbpf-tools/hardirqs.c -+++ b/libbpf-tools/hardirqs.c -@@ -185,9 +185,14 @@ int main(int argc, char **argv) - return 1; - } - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = hardirqs_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -@@ -207,27 +212,30 @@ int main(int argc, char **argv) - } - - if (env.count) { -- obj->links.handle__irq_handler = bpf_program__attach(obj->progs.handle__irq_handler); -- if (!obj->links.handle__irq_handler) { -- err = -errno; -+ obj->links.handle__irq_handler = -+ bpf_program__attach(obj->progs.handle__irq_handler); -+ err = libbpf_get_error(obj->links.handle__irq_handler); -+ if (err) { - fprintf(stderr, - "failed to attach irq/irq_handler_entry: %s\n", -- strerror(-err)); -+ strerror(err)); - } - } else { -- obj->links.irq_handler_entry = bpf_program__attach(obj->progs.irq_handler_entry); -- if (!obj->links.irq_handler_entry) { -- err = -errno; -+ obj->links.irq_handler_entry = -+ bpf_program__attach(obj->progs.irq_handler_entry); -+ err = libbpf_get_error(obj->links.irq_handler_entry); -+ if (err) { - fprintf(stderr, - "failed to attach irq_handler_entry: %s\n", -- strerror(-err)); -+ strerror(err)); - } -- obj->links.irq_handler_exit_exit = bpf_program__attach(obj->progs.irq_handler_exit_exit); -- if (!obj->links.irq_handler_exit_exit) { -- err = -errno; -+ obj->links.irq_handler_exit_exit = -+ bpf_program__attach(obj->progs.irq_handler_exit_exit); -+ err = libbpf_get_error(obj->links.irq_handler_exit_exit); -+ if (err) { - fprintf(stderr, - "failed to attach irq_handler_exit: %s\n", -- strerror(-err)); -+ strerror(err)); - } - } - -diff --git a/libbpf-tools/ksnoop.c b/libbpf-tools/ksnoop.c -index a6ea6107..a5f59a0f 100644 ---- a/libbpf-tools/ksnoop.c -+++ b/libbpf-tools/ksnoop.c -@@ -38,6 +38,7 @@ static bool verbose = false; - static __u32 filter_pid; - static bool stack_mode; - -+#define libbpf_errstr(val) strerror(-libbpf_get_error(val)) - - static void __p(enum log_level level, char *level_str, char *fmt, ...) - { -@@ -222,12 +223,14 @@ static int get_func_btf(struct btf *btf, struct func *func) - return -ENOENT; - } - type = btf__type_by_id(btf, func->id); -- if (!type || BTF_INFO_KIND(type->info) != BTF_KIND_FUNC) { -+ if (libbpf_get_error(type) || -+ BTF_INFO_KIND(type->info) != BTF_KIND_FUNC) { - p_err("Error looking up function type via id '%d'", func->id); - return -EINVAL; - } - type = btf__type_by_id(btf, type->type); -- if (!type || BTF_INFO_KIND(type->info) != BTF_KIND_FUNC_PROTO) { -+ if (libbpf_get_error(type) || -+ BTF_INFO_KIND(type->info) != BTF_KIND_FUNC_PROTO) { - p_err("Error looking up function proto type via id '%d'", - func->id); - return -EINVAL; -@@ -341,16 +344,15 @@ static int trace_to_value(struct btf *btf, struct func *func, char *argname, - static struct btf *get_btf(const char *name) - { - struct btf *mod_btf; -- int err; - - p_debug("getting BTF for %s", - name && strlen(name) > 0 ? name : "vmlinux"); - - if (!vmlinux_btf) { - vmlinux_btf = btf__load_vmlinux_btf(); -- if (!vmlinux_btf) { -- err = -errno; -- p_err("No BTF, cannot determine type info: %s", strerror(-err)); -+ if (libbpf_get_error(vmlinux_btf)) { -+ p_err("No BTF, cannot determine type info: %s", -+ libbpf_errstr(vmlinux_btf)); - return NULL; - } - } -@@ -358,9 +360,9 @@ static struct btf *get_btf(const char *name) - return vmlinux_btf; - - mod_btf = btf__load_module_btf(name, vmlinux_btf); -- if (!mod_btf) { -- err = -errno; -- p_err("No BTF for module '%s': %s", name, strerror(-err)); -+ if (libbpf_get_error(mod_btf)) { -+ p_err("No BTF for module '%s': %s", -+ name, libbpf_errstr(mod_btf)); - return NULL; - } - return mod_btf; -@@ -394,11 +396,11 @@ static char *type_id_to_str(struct btf *btf, __s32 type_id, char *str) - default: - do { - type = btf__type_by_id(btf, type_id); -- if (!type) { -+ -+ if (libbpf_get_error(type)) { - name = "?"; - break; - } -- - switch (BTF_INFO_KIND(type->info)) { - case BTF_KIND_CONST: - case BTF_KIND_VOLATILE: -@@ -553,17 +555,16 @@ static int parse_trace(char *str, struct trace *trace) - return ret; - } - trace->btf = get_btf(func->mod); -- if (!trace->btf) { -- ret = -errno; -+ if (libbpf_get_error(trace->btf)) { - p_err("could not get BTF for '%s': %s", - strlen(func->mod) ? func->mod : "vmlinux", -- strerror(-ret)); -+ libbpf_errstr(trace->btf)); - return -ENOENT; - } - trace->dump = btf_dump__new(trace->btf, NULL, &opts, trace_printf); -- if (!trace->dump) { -- ret = -errno; -- p_err("could not create BTF dump : %n", strerror(-ret)); -+ if (libbpf_get_error(trace->dump)) { -+ p_err("could not create BTF dump : %n", -+ libbpf_errstr(trace->btf)); - return -EINVAL; - } - -@@ -823,20 +824,20 @@ static int attach_traces(struct ksnoop_bpf *skel, struct trace *traces, - bpf_program__attach_kprobe(skel->progs.kprobe_entry, - false, - traces[i].func.name); -- if (!traces[i].links[0]) { -- ret = -errno; -+ ret = libbpf_get_error(traces[i].links[0]); -+ if (ret) { - p_err("Could not attach kprobe to '%s': %s", - traces[i].func.name, strerror(-ret)); - return ret; -- } -+ } - p_debug("Attached kprobe for '%s'", traces[i].func.name); - - traces[i].links[1] = - bpf_program__attach_kprobe(skel->progs.kprobe_return, - true, - traces[i].func.name); -- if (!traces[i].links[1]) { -- ret = -errno; -+ ret = libbpf_get_error(traces[i].links[1]); -+ if (ret) { - p_err("Could not attach kretprobe to '%s': %s", - traces[i].func.name, strerror(-ret)); - return ret; -@@ -848,6 +849,7 @@ static int attach_traces(struct ksnoop_bpf *skel, struct trace *traces, - - static int cmd_trace(int argc, char **argv) - { -+ struct perf_buffer_opts pb_opts = {}; - struct bpf_map *perf_map, *func_map; - struct perf_buffer *pb = NULL; - struct ksnoop_bpf *skel; -@@ -860,8 +862,7 @@ static int cmd_trace(int argc, char **argv) - - skel = ksnoop_bpf__open_and_load(); - if (!skel) { -- ret = -errno; -- p_err("Could not load ksnoop BPF: %s", strerror(-ret)); -+ p_err("Could not load ksnoop BPF: %s", libbpf_errstr(skel)); - return 1; - } - -@@ -886,11 +887,12 @@ static int cmd_trace(int argc, char **argv) - goto cleanup; - } - -- pb = perf_buffer__new(bpf_map__fd(perf_map), pages, -- trace_handler, lost_handler, NULL, NULL); -- if (!pb) { -- ret = -errno; -- p_err("Could not create perf buffer: %s", strerror(-ret)); -+ pb_opts.sample_cb = trace_handler; -+ pb_opts.lost_cb = lost_handler; -+ pb = perf_buffer__new(bpf_map__fd(perf_map), pages, &pb_opts); -+ if (libbpf_get_error(pb)) { -+ p_err("Could not create perf buffer: %s", -+ libbpf_errstr(pb)); - goto cleanup; - } - -@@ -904,8 +906,8 @@ static int cmd_trace(int argc, char **argv) - - while (!exiting) { - ret = perf_buffer__poll(pb, 1); -- if (ret < 0 && ret != -EINTR) { -- fprintf(stderr, "error polling perf buffer: %s\n", strerror(-ret)); -+ if (ret < 0 && errno != EINTR) { -+ fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - /* reset ret to return 0 if exiting */ -@@ -1005,7 +1007,6 @@ int main(int argc, char *argv[]) - if (argc < 0) - usage(); - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - - return cmd_select(argc, argv); -diff --git a/libbpf-tools/llcstat.bpf.c b/libbpf-tools/llcstat.bpf.c -index a36fc2df..fbd5b6c4 100644 ---- a/libbpf-tools/llcstat.bpf.c -+++ b/libbpf-tools/llcstat.bpf.c -@@ -36,13 +36,13 @@ int trace_event(__u64 sample_period, bool miss) - return 0; - } - --SEC("perf_event") -+SEC("perf_event/1") - int on_cache_miss(struct bpf_perf_event_data *ctx) - { - return trace_event(ctx->sample_period, true); - } - --SEC("perf_event") -+SEC("perf_event/2") - int on_cache_ref(struct bpf_perf_event_data *ctx) - { - return trace_event(ctx->sample_period, false); -diff --git a/libbpf-tools/llcstat.c b/libbpf-tools/llcstat.c -index be437bc2..150dd38b 100644 ---- a/libbpf-tools/llcstat.c -+++ b/libbpf-tools/llcstat.c -@@ -106,8 +106,10 @@ static int open_and_attach_perf_event(__u64 config, int period, - return -1; - } - links[i] = bpf_program__attach_perf_event(prog, fd); -- if (!links[i]) { -- fprintf(stderr, "failed to attach perf event on cpu: %d\n", i); -+ if (libbpf_get_error(links[i])) { -+ fprintf(stderr, "failed to attach perf event on cpu: " -+ "%d\n", i); -+ links[i] = NULL; - close(fd); - return -1; - } -@@ -182,9 +184,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - nr_cpus = libbpf_num_possible_cpus(); - if (nr_cpus < 0) { - fprintf(stderr, "failed to get # of possible cpus: '%s'!\n", -diff --git a/libbpf-tools/mountsnoop.c b/libbpf-tools/mountsnoop.c -index ac2acc45..0955f59e 100644 ---- a/libbpf-tools/mountsnoop.c -+++ b/libbpf-tools/mountsnoop.c -@@ -249,6 +249,7 @@ int main(int argc, char **argv) - .parser = parse_arg, - .doc = argp_program_doc, - }; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - struct mountsnoop_bpf *obj; - int err; -@@ -257,7 +258,11 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); -+ err = bump_memlock_rlimit(); -+ if (err) { -+ warn("failed to increase rlimit: %d\n", err); -+ return 1; -+ } - libbpf_set_print(libbpf_print_fn); - - obj = mountsnoop_bpf__open(); -@@ -280,10 +285,11 @@ int main(int argc, char **argv) - goto cleanup; - } - -- pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ pb_opts.sample_cb = handle_event; -+ pb_opts.lost_cb = handle_lost_events; -+ pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { - warn("failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -302,8 +308,8 @@ int main(int argc, char **argv) - - while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); -- if (err < 0 && err != -EINTR) { -- fprintf(stderr, "error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - /* reset err to return 0 if exiting */ -diff --git a/libbpf-tools/numamove.c b/libbpf-tools/numamove.c -index 0747f841..66a53ed6 100644 ---- a/libbpf-tools/numamove.c -+++ b/libbpf-tools/numamove.c -@@ -80,9 +80,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = numamove_bpf__open_and_load(); - if (!obj) { - fprintf(stderr, "failed to open and/or load BPF object\n"); -@@ -102,15 +107,18 @@ int main(int argc, char **argv) - - signal(SIGINT, sig_handler); - -- printf("%-10s %18s %18s\n", "TIME", "NUMA_migrations", "NUMA_migrations_ms"); -+ printf("%-10s %18s %18s\n", "TIME", "NUMA_migrations", -+ "NUMA_migrations_ms"); - while (!exiting) { - sleep(1); - time(&t); - tm = localtime(&t); - strftime(ts, sizeof(ts), "%H:%M:%S", tm); - printf("%-10s %18lld %18lld\n", ts, -- __atomic_exchange_n(&obj->bss->num, 0, __ATOMIC_RELAXED), -- __atomic_exchange_n(&obj->bss->latency, 0, __ATOMIC_RELAXED)); -+ __atomic_exchange_n(&obj->bss->num, 0, -+ __ATOMIC_RELAXED), -+ __atomic_exchange_n(&obj->bss->latency, 0, -+ __ATOMIC_RELAXED)); - } - - cleanup: -diff --git a/libbpf-tools/offcputime.c b/libbpf-tools/offcputime.c -index 37a8ec2c..0582b158 100644 ---- a/libbpf-tools/offcputime.c -+++ b/libbpf-tools/offcputime.c -@@ -279,9 +279,14 @@ int main(int argc, char **argv) - return 1; - } - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = offcputime_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -diff --git a/libbpf-tools/opensnoop.c b/libbpf-tools/opensnoop.c -index 557a63cd..5cdac0e5 100644 ---- a/libbpf-tools/opensnoop.c -+++ b/libbpf-tools/opensnoop.c -@@ -219,6 +219,7 @@ int main(int argc, char **argv) - .parser = parse_arg, - .doc = argp_program_doc, - }; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - struct opensnoop_bpf *obj; - __u64 time_end = 0; -@@ -228,9 +229,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = opensnoop_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -@@ -276,10 +282,13 @@ int main(int argc, char **argv) - printf("%s\n", "PATH"); - - /* setup event callbacks */ -+ pb_opts.sample_cb = handle_event; -+ pb_opts.lost_cb = handle_lost_events; - pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { -+ pb = NULL; - fprintf(stderr, "failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -297,8 +306,8 @@ int main(int argc, char **argv) - /* main: poll */ - while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); -- if (err < 0 && err != -EINTR) { -- fprintf(stderr, "error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - if (env.duration && get_ktime_ns() > time_end) -diff --git a/libbpf-tools/readahead.c b/libbpf-tools/readahead.c -index 17079389..77986011 100644 ---- a/libbpf-tools/readahead.c -+++ b/libbpf-tools/readahead.c -@@ -109,9 +109,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = readahead_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -diff --git a/libbpf-tools/runqlat.c b/libbpf-tools/runqlat.c -index 5a60b874..249bf794 100644 ---- a/libbpf-tools/runqlat.c -+++ b/libbpf-tools/runqlat.c -@@ -193,9 +193,14 @@ int main(int argc, char **argv) - return 1; - } - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = runqlat_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -diff --git a/libbpf-tools/runqlen.c b/libbpf-tools/runqlen.c -index 9cbbc739..2f6c5789 100644 ---- a/libbpf-tools/runqlen.c -+++ b/libbpf-tools/runqlen.c -@@ -145,8 +145,10 @@ static int open_and_attach_perf_event(int freq, struct bpf_program *prog, - return -1; - } - links[i] = bpf_program__attach_perf_event(prog, fd); -- if (!links[i]) { -- fprintf(stderr, "failed to attach perf event on cpu: %d\n", i); -+ if (libbpf_get_error(links[i])) { -+ fprintf(stderr, "failed to attach perf event on cpu: " -+ "%d\n", i); -+ links[i] = NULL; - close(fd); - return -1; - } -@@ -229,9 +231,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - nr_cpus = libbpf_num_possible_cpus(); - if (nr_cpus < 0) { - printf("failed to get # of possible cpus: '%s'!\n", -diff --git a/libbpf-tools/runqslower.c b/libbpf-tools/runqslower.c -index b038173e..b21894ca 100644 ---- a/libbpf-tools/runqslower.c -+++ b/libbpf-tools/runqslower.c -@@ -145,6 +145,7 @@ int main(int argc, char **argv) - .parser = parse_arg, - .doc = argp_program_doc, - }; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - struct runqslower_bpf *obj; - int err; -@@ -153,9 +154,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = runqslower_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -@@ -185,10 +191,12 @@ int main(int argc, char **argv) - else - printf("%-8s %-16s %-6s %14s\n", "TIME", "COMM", "TID", "LAT(us)"); - -- pb = perf_buffer__new(bpf_map__fd(obj->maps.events), 64, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ pb_opts.sample_cb = handle_event; -+ pb_opts.lost_cb = handle_lost_events; -+ pb = perf_buffer__new(bpf_map__fd(obj->maps.events), 64, &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { -+ pb = NULL; - fprintf(stderr, "failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -201,8 +209,8 @@ int main(int argc, char **argv) - - while (!exiting) { - err = perf_buffer__poll(pb, 100); -- if (err < 0 && err != -EINTR) { -- fprintf(stderr, "error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - /* reset err to return 0 if exiting */ -diff --git a/libbpf-tools/softirqs.c b/libbpf-tools/softirqs.c -index 34cfdb77..f1678d4c 100644 ---- a/libbpf-tools/softirqs.c -+++ b/libbpf-tools/softirqs.c -@@ -195,9 +195,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = softirqs_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -diff --git a/libbpf-tools/solisten.c b/libbpf-tools/solisten.c -index adaa668d..e5812f0c 100644 ---- a/libbpf-tools/solisten.c -+++ b/libbpf-tools/solisten.c -@@ -137,6 +137,7 @@ int main(int argc, char **argv) - .parser = parse_arg, - .doc = argp_program_doc, - }; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - struct solisten_bpf *obj; - int err; -@@ -145,7 +146,11 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); -+ err = bump_memlock_rlimit(); -+ if (err) { -+ warn("failed to increase rlimit: %d\n", err); -+ return 1; -+ } - libbpf_set_print(libbpf_print_fn); - - obj = solisten_bpf__open(); -@@ -175,10 +180,11 @@ int main(int argc, char **argv) - goto cleanup; - } - -- pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ pb_opts.sample_cb = handle_event; -+ pb_opts.lost_cb = handle_lost_events; -+ pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { - warn("failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -196,8 +202,8 @@ int main(int argc, char **argv) - - while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); -- if (err < 0 && err != -EINTR) { -- warn("error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ warn("error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - /* reset err to return 0 if exiting */ -diff --git a/libbpf-tools/statsnoop.c b/libbpf-tools/statsnoop.c -index 3f8f5c58..76779da6 100644 ---- a/libbpf-tools/statsnoop.c -+++ b/libbpf-tools/statsnoop.c -@@ -127,6 +127,7 @@ int main(int argc, char **argv) - .parser = parse_arg, - .doc = argp_program_doc, - }; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - struct statsnoop_bpf *obj; - int err; -@@ -135,9 +136,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); -+ err = bump_memlock_rlimit(); -+ if (err) { -+ warn("failed to increase rlimit: %d\n", err); -+ return 1; -+ } - libbpf_set_print(libbpf_print_fn); - -+ - obj = statsnoop_bpf__open(); - if (!obj) { - warn("failed to open BPF object\n"); -@@ -159,10 +165,12 @@ int main(int argc, char **argv) - goto cleanup; - } - -+ pb_opts.sample_cb = handle_event; -+ pb_opts.lost_cb = handle_lost_events; - pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { - warn("failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -180,8 +188,8 @@ int main(int argc, char **argv) - - while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); -- if (err < 0 && err != -EINTR) { -- warn("error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ warn("error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - /* reset err to return 0 if exiting */ -diff --git a/libbpf-tools/syscount.c b/libbpf-tools/syscount.c -index 2d687573..35c0e095 100644 ---- a/libbpf-tools/syscount.c -+++ b/libbpf-tools/syscount.c -@@ -390,9 +390,14 @@ int main(int argc, char **argv) - goto free_names; - } - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ warn("failed to increase rlimit: %s\n", strerror(errno)); -+ goto free_names; -+ } -+ - obj = syscount_bpf__open(); - if (!obj) { - warn("failed to open BPF object\n"); -@@ -418,15 +423,16 @@ int main(int argc, char **argv) - } - - obj->links.sys_exit = bpf_program__attach(obj->progs.sys_exit); -- if (!obj->links.sys_exit) { -- err = -errno; -- warn("failed to attach sys_exit program: %s\n", strerror(-err)); -+ err = libbpf_get_error(obj->links.sys_exit); -+ if (err) { -+ warn("failed to attach sys_exit program: %s\n", -+ strerror(-err)); - goto cleanup_obj; - } - if (env.latency) { - obj->links.sys_enter = bpf_program__attach(obj->progs.sys_enter); -- if (!obj->links.sys_enter) { -- err = -errno; -+ err = libbpf_get_error(obj->links.sys_enter); -+ if (err) { - warn("failed to attach sys_enter programs: %s\n", - strerror(-err)); - goto cleanup_obj; -diff --git a/libbpf-tools/tcpconnect.c b/libbpf-tools/tcpconnect.c -index 101cf72b..82b2bebb 100644 ---- a/libbpf-tools/tcpconnect.c -+++ b/libbpf-tools/tcpconnect.c -@@ -324,13 +324,17 @@ static void handle_lost_events(void *ctx, int cpu, __u64 lost_cnt) - - static void print_events(int perf_map_fd) - { -- struct perf_buffer *pb; -+ struct perf_buffer_opts pb_opts = { -+ .sample_cb = handle_event, -+ .lost_cb = handle_lost_events, -+ }; -+ struct perf_buffer *pb = NULL; - int err; - -- pb = perf_buffer__new(perf_map_fd, 128, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- err = -errno; -+ pb = perf_buffer__new(perf_map_fd, 128, &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { -+ pb = NULL; - warn("failed to open perf buffer: %d\n", err); - goto cleanup; - } -@@ -338,8 +342,8 @@ static void print_events(int perf_map_fd) - print_events_header(); - while (!exiting) { - err = perf_buffer__poll(pb, 100); -- if (err < 0 && err != -EINTR) { -- warn("error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ warn("error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - /* reset err to return 0 if exiting */ -@@ -365,9 +369,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ warn("failed to increase rlimit: %s\n", strerror(errno)); -+ return 1; -+ } -+ - obj = tcpconnect_bpf__open(); - if (!obj) { - warn("failed to open BPF object\n"); -diff --git a/libbpf-tools/tcpconnlat.c b/libbpf-tools/tcpconnlat.c -index 8eae76ae..3cab2115 100644 ---- a/libbpf-tools/tcpconnlat.c -+++ b/libbpf-tools/tcpconnlat.c -@@ -161,6 +161,7 @@ int main(int argc, char **argv) - .parser = parse_arg, - .doc = argp_program_doc, - }; -+ struct perf_buffer_opts pb_opts; - struct perf_buffer *pb = NULL; - struct tcpconnlat_bpf *obj; - int err; -@@ -169,9 +170,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = tcpconnlat_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -@@ -193,10 +199,15 @@ int main(int argc, char **argv) - goto cleanup; - } - -+ pb_opts.sample_cb = handle_event; -+ -+ pb_opts.lost_cb = handle_lost_events; - pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, -- handle_event, handle_lost_events, NULL, NULL); -- if (!pb) { -- fprintf(stderr, "failed to open perf buffer: %d\n", errno); -+ &pb_opts); -+ err = libbpf_get_error(pb); -+ if (err) { -+ pb = NULL; -+ fprintf(stderr, "failed to open perf buffer: %d\n", err); - goto cleanup; - } - -@@ -211,6 +222,7 @@ int main(int argc, char **argv) - "PID", "COMM", "IP", "SADDR", "DADDR", "DPORT", "LAT(ms)"); - } - -+ - if (signal(SIGINT, sig_int) == SIG_ERR) { - fprintf(stderr, "can't set signal handler: %s\n", strerror(errno)); - err = 1; -@@ -220,8 +232,8 @@ int main(int argc, char **argv) - /* main: poll */ - while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); -- if (err < 0 && err != -EINTR) { -- fprintf(stderr, "error polling perf buffer: %s\n", strerror(-err)); -+ if (err < 0 && errno != EINTR) { -+ fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno)); - goto cleanup; - } - /* reset err to return 0 if exiting */ -diff --git a/libbpf-tools/tcprtt.c b/libbpf-tools/tcprtt.c -index bed6efa7..bdff55bb 100644 ---- a/libbpf-tools/tcprtt.c -+++ b/libbpf-tools/tcprtt.c -@@ -225,9 +225,14 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %d\n", err); -+ return 1; -+ } -+ - obj = tcprtt_bpf__open(); - if (!obj) { - fprintf(stderr, "failed to open BPF object\n"); -diff --git a/libbpf-tools/trace_helpers.c b/libbpf-tools/trace_helpers.c -index 322b3c4f..f37015e7 100644 ---- a/libbpf-tools/trace_helpers.c -+++ b/libbpf-tools/trace_helpers.c -@@ -967,6 +967,16 @@ unsigned long long get_ktime_ns(void) - return ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec; - } - -+int bump_memlock_rlimit(void) -+{ -+ struct rlimit rlim_new = { -+ .rlim_cur = RLIM_INFINITY, -+ .rlim_max = RLIM_INFINITY, -+ }; -+ -+ return setrlimit(RLIMIT_MEMLOCK, &rlim_new); -+} -+ - bool is_kernel_module(const char *name) - { - bool found = false; -@@ -997,22 +1007,20 @@ bool fentry_exists(const char *name, const char *mod) - const struct btf_type *type; - const struct btf_enum *e; - char sysfs_mod[80]; -- int id = -1, i, err; -+ int id = -1, i; - - base = btf__parse(sysfs_vmlinux, NULL); -- if (!base) { -- err = -errno; -+ if (libbpf_get_error(base)) { - fprintf(stderr, "failed to parse vmlinux BTF at '%s': %s\n", -- sysfs_vmlinux, strerror(-err)); -+ sysfs_vmlinux, strerror(-libbpf_get_error(base))); - goto err_out; - } - if (mod && module_btf_exists(mod)) { - snprintf(sysfs_mod, sizeof(sysfs_mod), "/sys/kernel/btf/%s", mod); - btf = btf__parse_split(sysfs_mod, base); -- if (!btf) { -- err = -errno; -+ if (libbpf_get_error(btf)) { - fprintf(stderr, "failed to load BTF from %s: %s\n", -- sysfs_mod, strerror(-err)); -+ sysfs_mod, strerror(-libbpf_get_error(btf))); - btf = base; - base = NULL; - } -diff --git a/libbpf-tools/trace_helpers.h b/libbpf-tools/trace_helpers.h -index 98fd640f..61cbe433 100644 ---- a/libbpf-tools/trace_helpers.h -+++ b/libbpf-tools/trace_helpers.h -@@ -58,6 +58,7 @@ void print_linear_hist(unsigned int *vals, int vals_size, unsigned int base, - unsigned int step, const char *val_type); - - unsigned long long get_ktime_ns(void); -+int bump_memlock_rlimit(void); - - bool is_kernel_module(const char *name); - -diff --git a/libbpf-tools/vfsstat.c b/libbpf-tools/vfsstat.c -index 5519c366..3a8a51d8 100644 ---- a/libbpf-tools/vfsstat.c -+++ b/libbpf-tools/vfsstat.c -@@ -150,9 +150,15 @@ int main(int argc, char **argv) - if (err) - return err; - -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - libbpf_set_print(libbpf_print_fn); - -+ err = bump_memlock_rlimit(); -+ if (err) { -+ fprintf(stderr, "failed to increase rlimit: %s\n", -+ strerror(errno)); -+ return 1; -+ } -+ - skel = vfsstat_bpf__open(); - if (!skel) { - fprintf(stderr, "failed to open BPF skelect\n"); --- -2.35.1 - diff --git a/bcc-0.24.0-biolatency-biolatpcts-biosnoop-biotop-Build-fix-for-.patch b/bcc-0.24.0-biolatency-biolatpcts-biosnoop-biotop-Build-fix-for-.patch deleted file mode 100644 index da15c6e..0000000 --- a/bcc-0.24.0-biolatency-biolatpcts-biosnoop-biotop-Build-fix-for-.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 879792d2d47c1308e884fb59d92fe535f7bb8d71 Mon Sep 17 00:00:00 2001 -From: Tejun Heo -Date: Thu, 10 Mar 2022 08:37:21 -1000 -Subject: [PATCH 1/2] biolatency, biolatpcts, biosnoop, biotop: Build fix for - v5.17+ - -During 5.17 dev cycle, the kernel dropped request->rq_disk. It can now be -accessed through request->q->disk. Fix the python ones in tools/. There are -more usages in other places which need to be fixed too. - -Signed-off-by: Tejun Heo -Signed-off-by: Jerome Marchand ---- - tools/biolatency.py | 8 ++++++-- - tools/biolatpcts.py | 11 ++++++++--- - tools/biosnoop.py | 6 +++++- - tools/biotop.py | 9 +++++++-- - 4 files changed, 26 insertions(+), 8 deletions(-) - -diff --git a/tools/biolatency.py b/tools/biolatency.py -index 427cee47..10c852ac 100755 ---- a/tools/biolatency.py -+++ b/tools/biolatency.py -@@ -128,12 +128,16 @@ storage_str = "" - store_str = "" - if args.disks: - storage_str += "BPF_HISTOGRAM(dist, disk_key_t);" -- store_str += """ -+ disks_str = """ - disk_key_t key = {.slot = bpf_log2l(delta)}; -- void *__tmp = (void *)req->rq_disk->disk_name; -+ void *__tmp = (void *)req->__RQ_DISK__->disk_name; - bpf_probe_read(&key.disk, sizeof(key.disk), __tmp); - dist.atomic_increment(key); - """ -+ if BPF.kernel_struct_has_field(b'request', b'rq_disk'): -+ store_str += disks_str.replace('__RQ_DISK__', 'rq_disk') -+ else: -+ store_str += disks_str.replace('__RQ_DISK__', 'q->disk') - elif args.flags: - storage_str += "BPF_HISTOGRAM(dist, flag_key_t);" - store_str += """ -diff --git a/tools/biolatpcts.py b/tools/biolatpcts.py -index 0f334419..ea8b1ce6 100755 ---- a/tools/biolatpcts.py -+++ b/tools/biolatpcts.py -@@ -72,9 +72,9 @@ void kprobe_blk_account_io_done(struct pt_regs *ctx, struct request *rq, u64 now - if (!rq->__START_TIME_FIELD__) - return; - -- if (!rq->rq_disk || -- rq->rq_disk->major != __MAJOR__ || -- rq->rq_disk->first_minor != __MINOR__) -+ if (!rq->__RQ_DISK__ || -+ rq->__RQ_DISK__->major != __MAJOR__ || -+ rq->__RQ_DISK__->first_minor != __MINOR__) - return; - - cmd_flags = rq->cmd_flags; -@@ -142,6 +142,11 @@ bpf_source = bpf_source.replace('__START_TIME_FIELD__', start_time_field) - bpf_source = bpf_source.replace('__MAJOR__', str(major)) - bpf_source = bpf_source.replace('__MINOR__', str(minor)) - -+if BPF.kernel_struct_has_field(b'request', b'rq_disk'): -+ bpf_source = bpf_source.replace('__RQ_DISK__', 'rq_disk') -+else: -+ bpf_source = bpf_source.replace('__RQ_DISK__', 'q->disk') -+ - bpf = BPF(text=bpf_source) - if BPF.get_kprobe_functions(b'__blk_account_io_done'): - bpf.attach_kprobe(event="__blk_account_io_done", fn_name="kprobe_blk_account_io_done") -diff --git a/tools/biosnoop.py b/tools/biosnoop.py -index ae38e384..a2b636aa 100755 ---- a/tools/biosnoop.py -+++ b/tools/biosnoop.py -@@ -125,7 +125,7 @@ int trace_req_completion(struct pt_regs *ctx, struct request *req) - data.pid = valp->pid; - data.sector = req->__sector; - bpf_probe_read_kernel(&data.name, sizeof(data.name), valp->name); -- struct gendisk *rq_disk = req->rq_disk; -+ struct gendisk *rq_disk = req->__RQ_DISK__; - bpf_probe_read_kernel(&data.disk_name, sizeof(data.disk_name), - rq_disk->disk_name); - } -@@ -156,6 +156,10 @@ int trace_req_completion(struct pt_regs *ctx, struct request *req) - bpf_text = bpf_text.replace('##QUEUE##', '1') - else: - bpf_text = bpf_text.replace('##QUEUE##', '0') -+if BPF.kernel_struct_has_field(b'request', b'rq_disk'): -+ bpf_text = bpf_text.replace('__RQ_DISK__', 'rq_disk') -+else: -+ bpf_text = bpf_text.replace('__RQ_DISK__', 'q->disk') - if debug or args.ebpf: - print(bpf_text) - if args.ebpf: -diff --git a/tools/biotop.py b/tools/biotop.py -index b3e3ea00..882835f6 100755 ---- a/tools/biotop.py -+++ b/tools/biotop.py -@@ -129,8 +129,8 @@ int trace_req_completion(struct pt_regs *ctx, struct request *req) - - // setup info_t key - struct info_t info = {}; -- info.major = req->rq_disk->major; -- info.minor = req->rq_disk->first_minor; -+ info.major = req->__RQ_DISK__->major; -+ info.minor = req->__RQ_DISK__->first_minor; - /* - * The following deals with a kernel version change (in mainline 4.7, although - * it may be backported to earlier kernels) with how block request write flags -@@ -174,6 +174,11 @@ int trace_req_completion(struct pt_regs *ctx, struct request *req) - print(bpf_text) - exit() - -+if BPF.kernel_struct_has_field(b'request', b'rq_disk'): -+ bpf_text = bpf_text.replace('__RQ_DISK__', 'rq_disk') -+else: -+ bpf_text = bpf_text.replace('__RQ_DISK__', 'q->disk') -+ - b = BPF(text=bpf_text) - if BPF.get_kprobe_functions(b'__blk_account_io_start'): - b.attach_kprobe(event="__blk_account_io_start", fn_name="trace_pid_start") --- -2.35.1 - diff --git a/bcc-0.24.0-biolatpcts-Build-fixes-on-recent-kernels.patch b/bcc-0.24.0-biolatpcts-Build-fixes-on-recent-kernels.patch deleted file mode 100644 index e190cd5..0000000 --- a/bcc-0.24.0-biolatpcts-Build-fixes-on-recent-kernels.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 2ada4cee035c4d07391faa870a5df1874d657b65 Mon Sep 17 00:00:00 2001 -From: Tejun Heo -Date: Thu, 27 Jan 2022 06:25:31 -1000 -Subject: [PATCH 2/3] biolatpcts: Build fixes on recent kernels - -* `struct request` definition recently moved from blkdev.h to blk-mq.h - breaking both tools/biolatpcts and examples/tracing/biolatpcts. Fix them - by also including blk-mq.h. - -* blk_account_io_done() got split into two parts - inline condition checks - and the actual accounting with the latter now done in - __blk_account_io_done(). The kprobe attachment needs to be conditionalized - to work across the change. tools/biolatpcts was already updated but - examples/tracing/biolatpcts wasn't. Fix it. - -Signed-off-by: Tejun Heo ---- - examples/tracing/biolatpcts.py | 6 +++++- - tools/biolatpcts.py | 1 + - 2 files changed, 6 insertions(+), 1 deletion(-) - -diff --git a/examples/tracing/biolatpcts.py b/examples/tracing/biolatpcts.py -index c9bb834e..68a59516 100755 ---- a/examples/tracing/biolatpcts.py -+++ b/examples/tracing/biolatpcts.py -@@ -11,6 +11,7 @@ from time import sleep - - bpf_source = """ - #include -+#include - #include - #include - -@@ -45,7 +46,10 @@ void kprobe_blk_account_io_done(struct pt_regs *ctx, struct request *rq, u64 now - """ - - bpf = BPF(text=bpf_source) --bpf.attach_kprobe(event='blk_account_io_done', fn_name='kprobe_blk_account_io_done') -+if BPF.get_kprobe_functions(b'__blk_account_io_done'): -+ bpf.attach_kprobe(event="__blk_account_io_done", fn_name="kprobe_blk_account_io_done") -+else: -+ bpf.attach_kprobe(event="blk_account_io_done", fn_name="kprobe_blk_account_io_done") - - cur_lat_100ms = bpf['lat_100ms'] - cur_lat_1ms = bpf['lat_1ms'] -diff --git a/tools/biolatpcts.py b/tools/biolatpcts.py -index a2f59592..0f334419 100755 ---- a/tools/biolatpcts.py -+++ b/tools/biolatpcts.py -@@ -56,6 +56,7 @@ parser.add_argument('--verbose', '-v', action='count', default = 0) - bpf_source = """ - #include - #include -+#include - #include - - BPF_PERCPU_ARRAY(rwdf_100ms, u64, 400); --- -2.35.1 - diff --git a/bcc-0.24.0-libbpf-tools-Allow-to-use-different-cflags-for-bpf-t.patch b/bcc-0.24.0-libbpf-tools-Allow-to-use-different-cflags-for-bpf-t.patch deleted file mode 100644 index 5d40363..0000000 --- a/bcc-0.24.0-libbpf-tools-Allow-to-use-different-cflags-for-bpf-t.patch +++ /dev/null @@ -1,49 +0,0 @@ -From a6a5dba23d19f6a900b0359a7390df4a6b9a42f4 Mon Sep 17 00:00:00 2001 -From: Jerome Marchand -Date: Tue, 15 Mar 2022 17:59:24 +0100 -Subject: [PATCH 1/3] libbpf-tools: Allow to use different cflags for bpf - targets - -commit 531b698cdc20 ("libbpf-tools: Enable compilation warnings for -BPF programs") applies CFLAGS to all targets. However, some of the c -flags typically used by distribution are not available to the bpf -target. Add a new BPFCFLAGS macro to take care of that. - -Fixes the following compilation error on fedora: - - BPF bashreadline.bpf.o -clang-13: warning: optimization flag '-ffat-lto-objects' is not supported [-Wignored-optimization-argument] -clang-13: warning: argument unused during compilation: '-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1' [-Wunused-command-line-argument] -clang-13: warning: argument unused during compilation: '-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1' [-Wunused-command-line-argument] -clang-13: warning: argument unused during compilation: '-fstack-clash-protection' [-Wunused-command-line-argument] -error: option 'cf-protection=return' cannot be specified on this target -error: option 'cf-protection=branch' cannot be specified on this target -2 errors generated. ---- - libbpf-tools/Makefile | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/libbpf-tools/Makefile b/libbpf-tools/Makefile -index 6bf1ed08..39af95ec 100644 ---- a/libbpf-tools/Makefile -+++ b/libbpf-tools/Makefile -@@ -7,6 +7,7 @@ LIBBPF_SRC := $(abspath ../src/cc/libbpf/src) - LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a) - INCLUDES := -I$(OUTPUT) -I../src/cc/libbpf/include/uapi - CFLAGS := -g -O2 -Wall -+BPFCFLAGS := -g -O2 -Wall - INSTALL ?= install - prefix ?= /usr/local - ARCH := $(shell uname -m | sed 's/x86_64/x86/' | sed 's/aarch64/arm64/' | sed 's/ppc64le/powerpc/' | sed 's/mips.*/mips/') -@@ -106,7 +107,7 @@ $(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) - - $(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(ARCH)/vmlinux.h | $(OUTPUT) - $(call msg,BPF,$@) -- $(Q)$(CLANG) $(CFLAGS) -target bpf -D__TARGET_ARCH_$(ARCH) \ -+ $(Q)$(CLANG) $(BPFCFLAGS) -target bpf -D__TARGET_ARCH_$(ARCH) \ - -I$(ARCH)/ $(INCLUDES) -c $(filter %.c,$^) -o $@ && \ - $(LLVM_STRIP) -g $@ - --- -2.35.1 - diff --git a/bcc-0.24.0-libbpf-tools-Fix-dropped-request-rq_disk-for-kernel-.patch b/bcc-0.24.0-libbpf-tools-Fix-dropped-request-rq_disk-for-kernel-.patch deleted file mode 100644 index 8134d1f..0000000 --- a/bcc-0.24.0-libbpf-tools-Fix-dropped-request-rq_disk-for-kernel-.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 50480835adf15a389267393674504551b68987a2 Mon Sep 17 00:00:00 2001 -From: xingfeng2510 -Date: Wed, 30 Mar 2022 16:10:51 +0800 -Subject: [PATCH 2/2] libbpf-tools: Fix dropped request->rq_disk for kernel - 5.17+ - -Signed-off-by: Jerome Marchand ---- - libbpf-tools/biolatency.bpf.c | 20 ++++++++++++++++++-- - libbpf-tools/biosnoop.bpf.c | 12 +++++++++++- - libbpf-tools/biostacks.bpf.c | 12 +++++++++++- - libbpf-tools/bitesize.bpf.c | 12 +++++++++++- - 4 files changed, 51 insertions(+), 5 deletions(-) - -diff --git a/libbpf-tools/biolatency.bpf.c b/libbpf-tools/biolatency.bpf.c -index 648dda78..8f325046 100644 ---- a/libbpf-tools/biolatency.bpf.c -+++ b/libbpf-tools/biolatency.bpf.c -@@ -19,6 +19,10 @@ const volatile bool targ_ms = false; - const volatile bool filter_dev = false; - const volatile __u32 targ_dev = 0; - -+struct request_queue___x { -+ struct gendisk *disk; -+} __attribute__((preserve_access_index)); -+ - struct { - __uint(type, BPF_MAP_TYPE_CGROUP_ARRAY); - __type(key, u32); -@@ -53,9 +57,15 @@ int trace_rq_start(struct request *rq, int issue) - u64 ts = bpf_ktime_get_ns(); - - if (filter_dev) { -- struct gendisk *disk = BPF_CORE_READ(rq, rq_disk); -+ struct request_queue___x *q = (void *)BPF_CORE_READ(rq, q); -+ struct gendisk *disk; - u32 dev; - -+ if (bpf_core_field_exists(q->disk)) -+ disk = BPF_CORE_READ(q, disk); -+ else -+ disk = BPF_CORE_READ(rq, rq_disk); -+ - dev = disk ? MKDEV(BPF_CORE_READ(disk, major), - BPF_CORE_READ(disk, first_minor)) : 0; - if (targ_dev != dev) -@@ -119,7 +129,13 @@ int BPF_PROG(block_rq_complete, struct request *rq, int error, - goto cleanup; - - if (targ_per_disk) { -- struct gendisk *disk = BPF_CORE_READ(rq, rq_disk); -+ struct request_queue___x *q = (void *)BPF_CORE_READ(rq, q); -+ struct gendisk *disk; -+ -+ if (bpf_core_field_exists(q->disk)) -+ disk = BPF_CORE_READ(q, disk); -+ else -+ disk = BPF_CORE_READ(rq, rq_disk); - - hkey.dev = disk ? MKDEV(BPF_CORE_READ(disk, major), - BPF_CORE_READ(disk, first_minor)) : 0; -diff --git a/libbpf-tools/biosnoop.bpf.c b/libbpf-tools/biosnoop.bpf.c -index 54226e43..05903473 100644 ---- a/libbpf-tools/biosnoop.bpf.c -+++ b/libbpf-tools/biosnoop.bpf.c -@@ -15,6 +15,10 @@ const volatile __u32 targ_dev = 0; - - extern __u32 LINUX_KERNEL_VERSION __kconfig; - -+struct request_queue___x { -+ struct gendisk *disk; -+} __attribute__((preserve_access_index)); -+ - struct { - __uint(type, BPF_MAP_TYPE_CGROUP_ARRAY); - __type(key, u32); -@@ -92,7 +96,13 @@ int trace_rq_start(struct request *rq, bool insert) - - stagep = bpf_map_lookup_elem(&start, &rq); - if (!stagep) { -- struct gendisk *disk = BPF_CORE_READ(rq, rq_disk); -+ struct request_queue___x *q = (void *)BPF_CORE_READ(rq, q); -+ struct gendisk *disk; -+ -+ if (bpf_core_field_exists(q->disk)) -+ disk = BPF_CORE_READ(q, disk); -+ else -+ disk = BPF_CORE_READ(rq, rq_disk); - - stage.dev = disk ? MKDEV(BPF_CORE_READ(disk, major), - BPF_CORE_READ(disk, first_minor)) : 0; -diff --git a/libbpf-tools/biostacks.bpf.c b/libbpf-tools/biostacks.bpf.c -index 01993737..c13975fa 100644 ---- a/libbpf-tools/biostacks.bpf.c -+++ b/libbpf-tools/biostacks.bpf.c -@@ -14,6 +14,10 @@ const volatile bool targ_ms = false; - const volatile bool filter_dev = false; - const volatile __u32 targ_dev = -1; - -+struct request_queue___x { -+ struct gendisk *disk; -+} __attribute__((preserve_access_index)); -+ - struct internal_rqinfo { - u64 start_ts; - struct rqinfo rqinfo; -@@ -41,9 +45,15 @@ static __always_inline - int trace_start(void *ctx, struct request *rq, bool merge_bio) - { - struct internal_rqinfo *i_rqinfop = NULL, i_rqinfo = {}; -- struct gendisk *disk = BPF_CORE_READ(rq, rq_disk); -+ struct request_queue___x *q = (void *)BPF_CORE_READ(rq, q); -+ struct gendisk *disk; - u32 dev; - -+ if (bpf_core_field_exists(q->disk)) -+ disk = BPF_CORE_READ(q, disk); -+ else -+ disk = BPF_CORE_READ(rq, rq_disk); -+ - dev = disk ? MKDEV(BPF_CORE_READ(disk, major), - BPF_CORE_READ(disk, first_minor)) : 0; - if (filter_dev && targ_dev != dev) -diff --git a/libbpf-tools/bitesize.bpf.c b/libbpf-tools/bitesize.bpf.c -index 80672c9b..5066ca33 100644 ---- a/libbpf-tools/bitesize.bpf.c -+++ b/libbpf-tools/bitesize.bpf.c -@@ -13,6 +13,10 @@ const volatile __u32 targ_dev = 0; - - extern __u32 LINUX_KERNEL_VERSION __kconfig; - -+struct request_queue___x { -+ struct gendisk *disk; -+} __attribute__((preserve_access_index)); -+ - struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 10240); -@@ -41,9 +45,15 @@ static int trace_rq_issue(struct request *rq) - u64 slot; - - if (filter_dev) { -- struct gendisk *disk = BPF_CORE_READ(rq, rq_disk); -+ struct request_queue___x *q = (void *)BPF_CORE_READ(rq, q); -+ struct gendisk *disk; - u32 dev; - -+ if (bpf_core_field_exists(q->disk)) -+ disk = BPF_CORE_READ(q, disk); -+ else -+ disk = BPF_CORE_READ(rq, rq_disk); -+ - dev = disk ? MKDEV(BPF_CORE_READ(disk, major), - BPF_CORE_READ(disk, first_minor)) : 0; - if (targ_dev != dev) --- -2.35.1 - diff --git a/bcc-0.24.0-tools-include-blk-mq.h-in-bio-tools.patch b/bcc-0.24.0-tools-include-blk-mq.h-in-bio-tools.patch deleted file mode 100644 index 1f7ce06..0000000 --- a/bcc-0.24.0-tools-include-blk-mq.h-in-bio-tools.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 1eafb1f5aa0d3a9f60f89aad0ea55ae93899baff Mon Sep 17 00:00:00 2001 -From: Jerome Marchand -Date: Wed, 23 Feb 2022 16:04:30 +0100 -Subject: [PATCH 3/3] tools: include blk-mq.h in bio tools - -Kernel commit 24b83deb29b ("block: move struct request to blk-mq.h") -has moved struct request from blkdev.h to blk-mq.h. It results in -several bio tools to fail with errors of the following type: - -error: incomplete definition of type 'struct request' - -Since blk-mq.h had always included blkdev.h. it is safe to simply -replace the inclusion of blkdev.h by blk-mq-h. It works on both older -and newer kernel. - -Fixes: #3869 - -Signed-off-by: Jerome Marchand ---- - tools/biolatency.py | 2 +- - tools/biosnoop.py | 2 +- - tools/biotop.py | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/tools/biolatency.py b/tools/biolatency.py -index f4e2c9ea..427cee47 100755 ---- a/tools/biolatency.py -+++ b/tools/biolatency.py -@@ -64,7 +64,7 @@ debug = 0 - # define BPF program - bpf_text = """ - #include --#include -+#include - - typedef struct disk_key { - char disk[DISK_NAME_LEN]; -diff --git a/tools/biosnoop.py b/tools/biosnoop.py -index 2b954ac9..ae38e384 100755 ---- a/tools/biosnoop.py -+++ b/tools/biosnoop.py -@@ -37,7 +37,7 @@ debug = 0 - # define BPF program - bpf_text=""" - #include --#include -+#include - - // for saving the timestamp and __data_len of each request - struct start_req_t { -diff --git a/tools/biotop.py b/tools/biotop.py -index eac4dab9..b3e3ea00 100755 ---- a/tools/biotop.py -+++ b/tools/biotop.py -@@ -54,7 +54,7 @@ diskstats = "/proc/diskstats" - # load BPF program - bpf_text = """ - #include --#include -+#include - - // for saving the timestamp and __data_len of each request - struct start_req_t { --- -2.35.1 - diff --git a/bcc-0.24.0-tools-mdflush-include-blkdev.h-instead-of-genhd.h.patch b/bcc-0.24.0-tools-mdflush-include-blkdev.h-instead-of-genhd.h.patch deleted file mode 100644 index 18edfb4..0000000 --- a/bcc-0.24.0-tools-mdflush-include-blkdev.h-instead-of-genhd.h.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 93a464e2ef05b7ef78b5679e366b89fcddf6a575 Mon Sep 17 00:00:00 2001 -From: Jerome Marchand -Date: Mon, 1 Aug 2022 11:45:41 +0200 -Subject: [PATCH] tools/mdflush: include blkdev.h instead of genhd.h - -In recent kernels, i.e. since commit 322cbb50de71 ("block: remove -genhd.h"), genhd.h header has been removed and its content moved to -blkdev.h. Since genhd.h has been included in blkdev.h since forever, -including blkdev instead of genhd in the mdflush tool works for both -older and newer kernel. ---- - tools/mdflush.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tools/mdflush.py b/tools/mdflush.py -index 3581d1bf..6741d563 100755 ---- a/tools/mdflush.py -+++ b/tools/mdflush.py -@@ -19,7 +19,7 @@ from time import strftime - b = BPF(text=""" - #include - #include --#include -+#include - #include - - struct data_t { --- -2.37.1 - diff --git a/bcc-0.25.0-Fix-bpf_pseudo_fd-type-conversion-error.patch b/bcc-0.25.0-Fix-bpf_pseudo_fd-type-conversion-error.patch new file mode 100644 index 0000000..8463af4 --- /dev/null +++ b/bcc-0.25.0-Fix-bpf_pseudo_fd-type-conversion-error.patch @@ -0,0 +1,77 @@ +From c17a12ac030c5d9c812e611f8132570af0e795af Mon Sep 17 00:00:00 2001 +From: Yonghong Song +Date: Sat, 13 Aug 2022 17:50:07 -0700 +Subject: [PATCH 1/2] Fix bpf_pseudo_fd() type conversion error + +With llvm15 and llvm16, the following command line + sudo ./trace.py 'smp_call_function_single "%K", arg1' +will cause error: + /virtual/main.c:60:36: error: incompatible integer to pointer conversion passing 'u64' + (aka 'unsigned long long') to parameter of type 'void *' [-Wint-conversion] + bpf_perf_event_output(ctx, bpf_pseudo_fd(1, -1), CUR_CPU_IDENTIFIER, &__data, sizeof(__data)); + ^~~~~~~~~~~~~~~~~~~~ + 1 error generated. + Failed to compile BPF module + +In helpers.h, we have + u64 bpf_pseudo_fd(u64, u64) asm("llvm.bpf.pseudo"); +Apparently, <= llvm14 can tolerate u64 -> 'void *' conversion, but +llvm15 by default will cause an error. + +Let us explicitly convert bpf_pseudo_fd to 'void *' to avoid +such errors. + +Signed-off-by: Yonghong Song +--- + src/cc/frontends/clang/b_frontend_action.cc | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/cc/frontends/clang/b_frontend_action.cc b/src/cc/frontends/clang/b_frontend_action.cc +index a4e05b16..dbeba3e4 100644 +--- a/src/cc/frontends/clang/b_frontend_action.cc ++++ b/src/cc/frontends/clang/b_frontend_action.cc +@@ -957,7 +957,7 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) { + string arg0 = rewriter_.getRewrittenText(expansionRange(Call->getArg(0)->getSourceRange())); + string args_other = rewriter_.getRewrittenText(expansionRange(SourceRange(GET_BEGINLOC(Call->getArg(1)), + GET_ENDLOC(Call->getArg(2))))); +- txt = "bpf_perf_event_output(" + arg0 + ", bpf_pseudo_fd(1, " + fd + ")"; ++ txt = "bpf_perf_event_output(" + arg0 + ", (void *)bpf_pseudo_fd(1, " + fd + ")"; + txt += ", CUR_CPU_IDENTIFIER, " + args_other + ")"; + + // e.g. +@@ -986,7 +986,7 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) { + string meta_len = rewriter_.getRewrittenText(expansionRange(Call->getArg(3)->getSourceRange())); + txt = "bpf_perf_event_output(" + + skb + ", " + +- "bpf_pseudo_fd(1, " + fd + "), " + ++ "(void *)bpf_pseudo_fd(1, " + fd + "), " + + "((__u64)" + skb_len + " << 32) | BPF_F_CURRENT_CPU, " + + meta + ", " + + meta_len + ");"; +@@ -1006,12 +1006,12 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) { + string keyp = rewriter_.getRewrittenText(expansionRange(Call->getArg(1)->getSourceRange())); + string flag = rewriter_.getRewrittenText(expansionRange(Call->getArg(2)->getSourceRange())); + txt = "bpf_" + string(memb_name) + "(" + ctx + ", " + +- "bpf_pseudo_fd(1, " + fd + "), " + keyp + ", " + flag + ");"; ++ "(void *)bpf_pseudo_fd(1, " + fd + "), " + keyp + ", " + flag + ");"; + } else if (memb_name == "ringbuf_output") { + string name = string(Ref->getDecl()->getName()); + string args = rewriter_.getRewrittenText(expansionRange(SourceRange(GET_BEGINLOC(Call->getArg(0)), + GET_ENDLOC(Call->getArg(2))))); +- txt = "bpf_ringbuf_output(bpf_pseudo_fd(1, " + fd + ")"; ++ txt = "bpf_ringbuf_output((void *)bpf_pseudo_fd(1, " + fd + ")"; + txt += ", " + args + ")"; + + // e.g. +@@ -1033,7 +1033,7 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) { + } else if (memb_name == "ringbuf_reserve") { + string name = string(Ref->getDecl()->getName()); + string arg0 = rewriter_.getRewrittenText(expansionRange(Call->getArg(0)->getSourceRange())); +- txt = "bpf_ringbuf_reserve(bpf_pseudo_fd(1, " + fd + ")"; ++ txt = "bpf_ringbuf_reserve((void *)bpf_pseudo_fd(1, " + fd + ")"; + txt += ", " + arg0 + ", 0)"; // Flags in reserve are meaningless + } else if (memb_name == "ringbuf_discard") { + string name = string(Ref->getDecl()->getName()); +-- +2.38.1 + diff --git a/bcc-0.25.0-Fix-clang-15-int-to-pointer-conversion-errors.patch b/bcc-0.25.0-Fix-clang-15-int-to-pointer-conversion-errors.patch new file mode 100644 index 0000000..780975c --- /dev/null +++ b/bcc-0.25.0-Fix-clang-15-int-to-pointer-conversion-errors.patch @@ -0,0 +1,96 @@ +From 9ae3908ae38b3e8d8e36a52c0e5664c453d4c015 Mon Sep 17 00:00:00 2001 +From: Jerome Marchand +Date: Wed, 26 Oct 2022 14:41:54 +0200 +Subject: [PATCH 2/2] Fix clang 15 int to pointer conversion errors + +Since version 15, clang issues error for implicit conversion of +integer to pointer. Several tools are broken. This patch add explicit +pointer cast where needed. + +Fixes the following errors: +/virtual/main.c:37:18: error: incompatible integer to pointer conversion initializing 'struct request *' with an expression of type 'unsigned long' [-Wint-conversion] + struct request *req = ctx->di; + ^ ~~~~~~~ +/virtual/main.c:49:18: error: incompatible integer to pointer conversion initializing 'struct request *' with an expression of type 'unsigned long' [-Wint-conversion] + struct request *req = ctx->di; + ^ ~~~~~~~ +2 errors generated. + +/virtual/main.c:73:19: error: incompatible integer to pointer conversion initializing 'struct pt_regs *' with an expression of type 'unsigned long' [-Wint-conversion] + struct pt_regs * __ctx = ctx->di; + ^ ~~~~~~~ +/virtual/main.c:100:240: error: incompatible integer to pointer conversion passing 'u64' (aka 'unsigned long long') to parameter of type 'const void *' [-Wint-conversion] + data.ppid = ({ typeof(pid_t) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&({ typeof(struct task_struct *) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&task->real_parent); _val; })->tgid); _val; }); + ^~~~~~~~~~~~~~~~~~~~~~~ +/virtual/main.c:100:118: error: incompatible integer to pointer conversion passing 'u64' (aka 'unsigned long long') to parameter of type 'const void *' [-Wint-conversion] + data.ppid = ({ typeof(pid_t) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&({ typeof(struct task_struct *) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&task->real_parent); _val; })->tgid); _val; }); + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Jerome Marchand +--- + src/cc/frontends/clang/b_frontend_action.cc | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/src/cc/frontends/clang/b_frontend_action.cc b/src/cc/frontends/clang/b_frontend_action.cc +index dbeba3e4..c0582464 100644 +--- a/src/cc/frontends/clang/b_frontend_action.cc ++++ b/src/cc/frontends/clang/b_frontend_action.cc +@@ -517,9 +517,9 @@ bool ProbeVisitor::VisitUnaryOperator(UnaryOperator *E) { + string pre, post; + pre = "({ typeof(" + E->getType().getAsString() + ") _val; __builtin_memset(&_val, 0, sizeof(_val));"; + if (cannot_fall_back_safely) +- pre += " bpf_probe_read_kernel(&_val, sizeof(_val), (u64)"; ++ pre += " bpf_probe_read_kernel(&_val, sizeof(_val), (void *)"; + else +- pre += " bpf_probe_read(&_val, sizeof(_val), (u64)"; ++ pre += " bpf_probe_read(&_val, sizeof(_val), (void *)"; + post = "); _val; })"; + rewriter_.ReplaceText(expansionLoc(E->getOperatorLoc()), 1, pre); + rewriter_.InsertTextAfterToken(expansionLoc(GET_ENDLOC(sub)), post); +@@ -581,9 +581,9 @@ bool ProbeVisitor::VisitMemberExpr(MemberExpr *E) { + string pre, post; + pre = "({ typeof(" + E->getType().getAsString() + ") _val; __builtin_memset(&_val, 0, sizeof(_val));"; + if (cannot_fall_back_safely) +- pre += " bpf_probe_read_kernel(&_val, sizeof(_val), (u64)&"; ++ pre += " bpf_probe_read_kernel(&_val, sizeof(_val), (void *)&"; + else +- pre += " bpf_probe_read(&_val, sizeof(_val), (u64)&"; ++ pre += " bpf_probe_read(&_val, sizeof(_val), (void *)&"; + post = rhs + "); _val; })"; + rewriter_.InsertText(expansionLoc(GET_BEGINLOC(E)), pre); + rewriter_.ReplaceText(expansionRange(SourceRange(member, GET_ENDLOC(E))), post); +@@ -635,9 +635,9 @@ bool ProbeVisitor::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { + + pre = "({ typeof(" + E->getType().getAsString() + ") _val; __builtin_memset(&_val, 0, sizeof(_val));"; + if (cannot_fall_back_safely) +- pre += " bpf_probe_read_kernel(&_val, sizeof(_val), (u64)(("; ++ pre += " bpf_probe_read_kernel(&_val, sizeof(_val), (void *)(("; + else +- pre += " bpf_probe_read(&_val, sizeof(_val), (u64)(("; ++ pre += " bpf_probe_read(&_val, sizeof(_val), (void *)(("; + if (isMemberDereference(base)) { + pre += "&"; + // If the base of the array subscript is a member dereference, we'll rewrite +@@ -747,8 +747,8 @@ void BTypeVisitor::genParamDirectAssign(FunctionDecl *D, string& preamble, + arg->addAttr(UnavailableAttr::CreateImplicit(C, "ptregs")); + size_t d = idx - 1; + const char *reg = calling_conv_regs[d]; +- preamble += " " + text + " = " + fn_args_[0]->getName().str() + "->" + +- string(reg) + ";"; ++ preamble += " " + text + " = (" + arg->getType().getAsString() + ")" + ++ fn_args_[0]->getName().str() + "->" + string(reg) + ";"; + } + } + } +@@ -762,7 +762,7 @@ void BTypeVisitor::genParamIndirectAssign(FunctionDecl *D, string& preamble, + + if (idx == 0) { + new_ctx = "__" + arg->getName().str(); +- preamble += " struct pt_regs * " + new_ctx + " = " + ++ preamble += " struct pt_regs * " + new_ctx + " = (void *)" + + arg->getName().str() + "->" + + string(calling_conv_regs[0]) + ";"; + } else { +-- +2.38.1 + diff --git a/bcc-0.25.0-Fix-some-documentation-issues-4197.patch b/bcc-0.25.0-Fix-some-documentation-issues-4197.patch new file mode 100644 index 0000000..9c879af --- /dev/null +++ b/bcc-0.25.0-Fix-some-documentation-issues-4197.patch @@ -0,0 +1,222 @@ +From 2f6565681e627d11dde0177503100669df020684 Mon Sep 17 00:00:00 2001 +From: Jerome Marchand +Date: Sun, 28 Aug 2022 07:44:01 +0200 +Subject: [PATCH] Fix some documentation issues (#4197) + +* compactsnoop-manpage: fix the name of the tool in the NAME section +In its manpage, compactsnoop tools is called compacstall in the NAME +section. I don't know where that name comes from, but it should be +compactsnoop. + +* dirtop-manpage: use '-d' option in the EXAMPLES section +The mandatory '-d' option of dirtop is missing in the EXAMPLES +section. Copy it from the usage message. Also remove '.py' suffixes. + +* funclatency-manpage: fix typo in one of the examples +There is a spurious colon in one of the manpage examples. Remove it. + +* tools/killsnoop: add '-s' option in the synopsis of the example file +Commit 33c8b1ac ("Update man page and example file") added '-s' option +to the manpage and an example in the example file, but missed the +sysnopsis in that later case. + +* trace-manpage: add missing options (-c,-n,-f and -B) to the synopsis +Copy the full sysopsis from the usage message. + +* tcptracer-manpage: add missing '-t' option in the manpage +Add '-t' option to the synopsis and description. + +* tcpsubnet-manpage: remove '--ebpf' option from the manpage +This option is explicitly suppressed in argparse and no manpage of +other tools mentions it. + +* manpages: remove '.py' suffix from the synopsis of some *snoop tools +Other manpages don't show the suffix, nor do the usage messages. +--- + man/man8/bindsnoop.8 | 2 +- + man/man8/compactsnoop.8 | 4 ++-- + man/man8/dirtop.8 | 8 ++++---- + man/man8/drsnoop.8 | 2 +- + man/man8/funclatency.8 | 2 +- + man/man8/opensnoop.8 | 2 +- + man/man8/tcpsubnet.8 | 5 +---- + man/man8/tcptracer.8 | 5 ++++- + man/man8/trace.8 | 6 ++++-- + tools/killsnoop_example.txt | 2 ++ + 10 files changed, 21 insertions(+), 17 deletions(-) + +diff --git a/man/man8/bindsnoop.8 b/man/man8/bindsnoop.8 +index f8fa1850..0eb42ccb 100644 +--- a/man/man8/bindsnoop.8 ++++ b/man/man8/bindsnoop.8 +@@ -2,7 +2,7 @@ + .SH NAME + bindsnoop \- Trace bind() system calls. + .SH SYNOPSIS +-.B bindsnoop.py [\fB-h\fP] [\fB-w\fP] [\fB-t\fP] [\fB-p\fP PID] [\fB-P\fP PORT] [\fB-E\fP] [\fB-U\fP] [\fB-u\fP UID] [\fB--count\fP] [\fB--cgroupmap MAP\fP] [\fB--mntnsmap MNTNSMAP\fP] ++.B bindsnoop [\fB-h\fP] [\fB-w\fP] [\fB-t\fP] [\fB-p\fP PID] [\fB-P\fP PORT] [\fB-E\fP] [\fB-U\fP] [\fB-u\fP UID] [\fB--count\fP] [\fB--cgroupmap MAP\fP] [\fB--mntnsmap MNTNSMAP\fP] + .SH DESCRIPTION + bindsnoop reports socket options set before the bind call that would impact this system call behavior. + .PP +diff --git a/man/man8/compactsnoop.8 b/man/man8/compactsnoop.8 +index a2933d7a..e9cde0ce 100644 +--- a/man/man8/compactsnoop.8 ++++ b/man/man8/compactsnoop.8 +@@ -1,8 +1,8 @@ + .TH compactsnoop 8 "2019-11-1" "USER COMMANDS" + .SH NAME +-compactstall \- Trace compact zone events. Uses Linux eBPF/bcc. ++compactsnoop \- Trace compact zone events. Uses Linux eBPF/bcc. + .SH SYNOPSIS +-.B compactsnoop.py [\-h] [\-T] [\-p PID] [\-d DURATION] [\-K] [\-e] ++.B compactsnoop [\-h] [\-T] [\-p PID] [\-d DURATION] [\-K] [\-e] + .SH DESCRIPTION + compactsnoop traces the compact zone events, showing which processes are + allocing pages with memory compaction. This can be useful for discovering +diff --git a/man/man8/dirtop.8 b/man/man8/dirtop.8 +index cc61a676..eaa0c0c4 100644 +--- a/man/man8/dirtop.8 ++++ b/man/man8/dirtop.8 +@@ -55,19 +55,19 @@ Number of interval summaries. + .TP + Summarize block device I/O by directory, 1 second screen refresh: + # +-.B dirtop.py ++.B dirtop -d '/hdfs/uuid/*/yarn' + .TP + Don't clear the screen, and top 8 rows only: + # +-.B dirtop.py -Cr 8 ++.B dirtop -d '/hdfs/uuid/*/yarn' -Cr 8 + .TP + 5 second summaries, 10 times only: + # +-.B dirtop.py 5 10 ++.B dirtop -d '/hdfs/uuid/*/yarn' 5 10 + .TP + Report read & write IOs generated in mutliple yarn and data directories: + # +-.B dirtop.py -d '/hdfs/uuid/*/yarn,/hdfs/uuid/*/data' ++.B dirtop -d '/hdfs/uuid/*/yarn,/hdfs/uuid/*/data' + .SH FIELDS + .TP + loadavg: +diff --git a/man/man8/drsnoop.8 b/man/man8/drsnoop.8 +index 90ca901f..8fb3789a 100644 +--- a/man/man8/drsnoop.8 ++++ b/man/man8/drsnoop.8 +@@ -2,7 +2,7 @@ + .SH NAME + drsnoop \- Trace direct reclaim events. Uses Linux eBPF/bcc. + .SH SYNOPSIS +-.B drsnoop.py [\-h] [\-T] [\-U] [\-p PID] [\-t TID] [\-u UID] [\-d DURATION] [-n name] [-v] ++.B drsnoop [\-h] [\-T] [\-U] [\-p PID] [\-t TID] [\-u UID] [\-d DURATION] [-n name] [-v] + .SH DESCRIPTION + drsnoop trace direct reclaim events, showing which processes are allocing pages + with direct reclaiming. This can be useful for discovering when allocstall (/p- +diff --git a/man/man8/funclatency.8 b/man/man8/funclatency.8 +index 9012b832..f96f6098 100644 +--- a/man/man8/funclatency.8 ++++ b/man/man8/funclatency.8 +@@ -89,7 +89,7 @@ Print the BPF program (for debugging purposes). + .TP + Time vfs_read() for process ID 181 only: + # +-.B funclatency \-p 181 vfs_read: ++.B funclatency \-p 181 vfs_read + .TP + Time both vfs_fstat() and vfs_fstatat() calls, by use of a wildcard: + # +diff --git a/man/man8/opensnoop.8 b/man/man8/opensnoop.8 +index fee83263..d1888772 100644 +--- a/man/man8/opensnoop.8 ++++ b/man/man8/opensnoop.8 +@@ -2,7 +2,7 @@ + .SH NAME + opensnoop \- Trace open() syscalls. Uses Linux eBPF/bcc. + .SH SYNOPSIS +-.B opensnoop.py [\-h] [\-T] [\-U] [\-x] [\-p PID] [\-t TID] [\-u UID] ++.B opensnoop [\-h] [\-T] [\-U] [\-x] [\-p PID] [\-t TID] [\-u UID] + [\-d DURATION] [\-n NAME] [\-e] [\-f FLAG_FILTER] + [--cgroupmap MAPPATH] [--mntnsmap MAPPATH] + .SH DESCRIPTION +diff --git a/man/man8/tcpsubnet.8 b/man/man8/tcpsubnet.8 +index 525b8082..ad5f1be1 100644 +--- a/man/man8/tcpsubnet.8 ++++ b/man/man8/tcpsubnet.8 +@@ -2,7 +2,7 @@ + .SH NAME + tcpsubnet \- Summarize and aggregate IPv4 TCP traffic by subnet. + .SH SYNOPSIS +-.B tcpsubnet [\-h] [\-v] [\--ebpf] [\-J] [\-f FORMAT] [\-i INTERVAL] [subnets] ++.B tcpsubnet [\-h] [\-v] [\-J] [\-f FORMAT] [\-i INTERVAL] [subnets] + .SH DESCRIPTION + This tool summarizes and aggregates IPv4 TCP sent to the subnets + passed in argument and prints to stdout on a fixed interval. +@@ -35,9 +35,6 @@ Interval between updates, seconds (default 1). + Format output units. Supported values are bkmBKM. When using + kmKM the output will be rounded to floor. + .TP +-\--ebpf +-Prints the BPF program. +-.TP + subnets + Comma separated list of subnets. Traffic will be categorized + in theses subnets. Order matters. +diff --git a/man/man8/tcptracer.8 b/man/man8/tcptracer.8 +index 59240f4b..19a6164d 100644 +--- a/man/man8/tcptracer.8 ++++ b/man/man8/tcptracer.8 +@@ -2,7 +2,7 @@ + .SH NAME + tcptracer \- Trace TCP established connections. Uses Linux eBPF/bcc. + .SH SYNOPSIS +-.B tcptracer [\-h] [\-v] [\-p PID] [\-N NETNS] [\-\-cgroupmap MAPPATH] [--mntnsmap MAPPATH] [\-4 | \-6] ++.B tcptracer [\-h] [\-v] [-t] [\-p PID] [\-N NETNS] [\-\-cgroupmap MAPPATH] [--mntnsmap MAPPATH] [\-4 | \-6] + .SH DESCRIPTION + This tool traces established TCP connections that open and close while tracing, + and prints a line of output per connect, accept and close events. This includes +@@ -23,6 +23,9 @@ Print usage message. + \-v + Print full lines, with long event type names and network namespace numbers. + .TP ++\-t ++Include timestamp on output ++.TP + \-p PID + Trace this process ID only (filtered in-kernel). + .TP +diff --git a/man/man8/trace.8 b/man/man8/trace.8 +index c4417e5f..64a5e799 100644 +--- a/man/man8/trace.8 ++++ b/man/man8/trace.8 +@@ -2,9 +2,11 @@ + .SH NAME + trace \- Trace a function and print its arguments or return value, optionally evaluating a filter. Uses Linux eBPF/bcc. + .SH SYNOPSIS +-.B trace [-h] [-b BUFFER_PAGES] [-p PID] [-L TID] [--uid UID] [-v] [-Z STRING_SIZE] [-S] [-s SYM_FILE_LIST] +- [-M MAX_EVENTS] [-t] [-u] [-T] [-C] [-K] [-U] [-a] [-I header] [-A] ++.B trace [-h] [-b BUFFER_PAGES] [-p PID] [-L TID] [--uid UID] [-v] [-Z STRING_SIZE] [-S] [-M MAX_EVENTS] [-t] ++ [-u] [-T] [-C] [-c CGROUP_PATH] [-n NAME] [-f MSG_FILTER] [-B] [-s SYM_FILE_LIST] [-K] [-U] [-a] ++ [-I header] [-A] + probe [probe ...] ++ + .SH DESCRIPTION + trace probes functions you specify and displays trace messages if a particular + condition is met. You can control the message format to display function +diff --git a/tools/killsnoop_example.txt b/tools/killsnoop_example.txt +index 7746f2a0..038d09c6 100644 +--- a/tools/killsnoop_example.txt ++++ b/tools/killsnoop_example.txt +@@ -27,6 +27,8 @@ Trace signals issued by the kill() syscall + -h, --help show this help message and exit + -x, --failed only show failed kill syscalls + -p PID, --pid PID trace this PID only ++ -s SIGNAL, --signal SIGNAL ++ trace this signal only + + examples: + ./killsnoop # trace all kill() signals +-- +2.38.1 + diff --git a/bcc-0.25.0-bcc-support-building-with-external-libbpf-package-an.patch b/bcc-0.25.0-bcc-support-building-with-external-libbpf-package-an.patch new file mode 100644 index 0000000..bb18031 --- /dev/null +++ b/bcc-0.25.0-bcc-support-building-with-external-libbpf-package-an.patch @@ -0,0 +1,100 @@ +From 2e14fbaf9105e0b504f243ffc6d7d5a16e13a2a7 Mon Sep 17 00:00:00 2001 +From: Alan Maguire +Date: Fri, 14 Oct 2022 13:01:58 +0000 +Subject: [PATCH] bcc: support building with external libbpf package and older + uapi linux/bpf.h + +When building bcc with a relatively new packaged libbpf (0.8.1) +and -DCMAKE_USE_LIBBPF_PACKAGE:BOOL=TRUE, multiple compilation +failures are encountered due the fact the system uapi header +in /usr/include/linux/bpf.h is not very recent (this is often +the case for distros, which sync it via a kernel headers +package quite conservatively due to use by glibc). + +With libbpf built via git submodule, the uapi header included in +the libbpf package is used, so here a similar approach is proposed +for the external package build. Instead of having to sync +another file the already present compat/linux/virtual_bpf.h +is used; we copy it to compat/linux/bpf.h (eliminating the +string prefix/suffix on first/last lines). + +From there, we ensure that places that assume the presence of +the libbpf git submodule point at compat/ as a location to +find the uapi header. + +Signed-off-by: Alan Maguire +--- + examples/cpp/CMakeLists.txt | 4 ++++ + introspection/CMakeLists.txt | 4 ++++ + src/cc/CMakeLists.txt | 6 ++++++ + tests/cc/CMakeLists.txt | 4 ++++ + 4 files changed, 18 insertions(+) + +diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt +index 801e6bad..8d09ae11 100644 +--- a/examples/cpp/CMakeLists.txt ++++ b/examples/cpp/CMakeLists.txt +@@ -4,7 +4,11 @@ + include_directories(${PROJECT_BINARY_DIR}/src/cc) + include_directories(${PROJECT_SOURCE_DIR}/src/cc) + include_directories(${PROJECT_SOURCE_DIR}/src/cc/api) ++if (CMAKE_USE_LIBBPF_PACKAGE AND LIBBPF_FOUND) ++include_directories(${PROJECT_SOURCE_DIR}/src/cc/compat) ++else() + include_directories(${PROJECT_SOURCE_DIR}/src/cc/libbpf/include/uapi) ++endif() + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") +diff --git a/introspection/CMakeLists.txt b/introspection/CMakeLists.txt +index dcbe69a3..ce2d03dc 100644 +--- a/introspection/CMakeLists.txt ++++ b/introspection/CMakeLists.txt +@@ -3,7 +3,11 @@ + + include_directories(${PROJECT_SOURCE_DIR}/src/cc) + include_directories(${PROJECT_SOURCE_DIR}/src/cc/api) ++if (CMAKE_USE_LIBBPF_PACKAGE AND LIBBPF_FOUND) ++include_directories(${PROJECT_SOURCE_DIR}/src/cc/compat) ++else() + include_directories(${PROJECT_SOURCE_DIR}/src/cc/libbpf/include/uapi) ++endif() + + option(INSTALL_INTROSPECTION "Install BPF introspection tools" ON) + option(BPS_LINK_RT "Pass -lrt to linker when linking bps tool" ON) +diff --git a/src/cc/CMakeLists.txt b/src/cc/CMakeLists.txt +index ffe8feec..c7f53530 100644 +--- a/src/cc/CMakeLists.txt ++++ b/src/cc/CMakeLists.txt +@@ -15,6 +15,12 @@ endif (LIBDEBUGINFOD_FOUND) + # todo: if check for kernel version + if (CMAKE_USE_LIBBPF_PACKAGE AND LIBBPF_FOUND) + include_directories(${LIBBPF_INCLUDE_DIRS}) ++ # create up-to-date linux/bpf.h from virtual_bpf.h (remove string wrapper); ++ # when libbpf is built as a submodule we use its version of linux/bpf.h ++ # so this does similar for the libbpf package, removing reliance on the ++ # system uapi header which can be out of date. ++ execute_process(COMMAND sh -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/compat/linux && grep -ve '\\*\\*\\*\\*' virtual_bpf.h > bpf.h") ++ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/compat) + else() + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libbpf/include) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libbpf/include/uapi) +diff --git a/tests/cc/CMakeLists.txt b/tests/cc/CMakeLists.txt +index 677867d7..47056455 100644 +--- a/tests/cc/CMakeLists.txt ++++ b/tests/cc/CMakeLists.txt +@@ -3,7 +3,11 @@ + + include_directories(${PROJECT_SOURCE_DIR}/src/cc) + include_directories(${PROJECT_SOURCE_DIR}/src/cc/api) ++if (CMAKE_USE_LIBBPF_PACKAGE AND LIBBPF_FOUND) ++include_directories(${PROJECT_SOURCE_DIR}/src/cc/compat) ++else() + include_directories(${PROJECT_SOURCE_DIR}/src/cc/libbpf/include/uapi) ++endif() + include_directories(${PROJECT_SOURCE_DIR}/tests/python/include) + + add_executable(test_static test_static.c) +-- +2.37.3 + diff --git a/bcc-0.25.0-tools-nfsslower-fix-an-uninitialized-struct-error.patch b/bcc-0.25.0-tools-nfsslower-fix-an-uninitialized-struct-error.patch new file mode 100644 index 0000000..dcd2937 --- /dev/null +++ b/bcc-0.25.0-tools-nfsslower-fix-an-uninitialized-struct-error.patch @@ -0,0 +1,64 @@ +From acc8800b6f4380b6f4c7f04ee9a1263cf11deb35 Mon Sep 17 00:00:00 2001 +From: Jerome Marchand +Date: Tue, 20 Dec 2022 11:33:51 +0100 +Subject: [PATCH] tools: nfsslower: fix an uninitialized struct error + +Fixes the following error: +bpf: Failed to load program: Permission denied +reg type unsupported for arg#0 function trace_read_return#22 +0: R1=ctx(off=0,imm=0) R10=fp0 +; int trace_read_return(struct pt_regs *ctx) +0: (bf) r6 = r1 ; R1=ctx(off=0,imm=0) R6_w=ctx(off=0,imm=0) + +[...] + +; bpf_probe_read_kernel(&data.file, sizeof(data.file), (void *)qs.name); +75: (b7) r2 = 32 ; R2_w=32 +76: (85) call bpf_probe_read_kernel#113 ; R0_w=scalar() fp-16=????mmmm fp-24=mmmmmmmm fp-32=mmmmmmmm fp-40=mmmmmmmm fp-48=mmmmmmmm +; bpf_perf_event_output(ctx, (void *)bpf_pseudo_fd(1, -2), CUR_CPU_IDENTIFIER, &data, sizeof(data)); +77: (18) r2 = 0xffff9a0a42177200 ; R2_w=map_ptr(off=0,ks=4,vs=4,imm=0) +79: (bf) r4 = r10 ; R4_w=fp0 R10=fp0 +; bpf_probe_read_kernel(&data.file, sizeof(data.file), (void *)qs.name); +80: (07) r4 += -104 ; R4_w=fp-104 +; bpf_perf_event_output(ctx, (void *)bpf_pseudo_fd(1, -2), CUR_CPU_IDENTIFIER, &data, sizeof(data)); +81: (bf) r1 = r6 ; R1_w=ctx(off=0,imm=0) R6=ctx(off=0,imm=0) +82: (18) r3 = 0xffffffff ; R3_w=4294967295 +84: (b7) r5 = 96 ; R5_w=96 +85: (85) call bpf_perf_event_output#25 +invalid indirect read from stack R4 off -104+92 size 96 +processed 82 insns (limit 1000000) max_states_per_insn 0 total_states 4 peak_states 4 mark_read 3 + +Traceback (most recent call last): + File "/usr/share/bcc/tools/nfsslower", line 283, in + b.attach_kretprobe(event="nfs_file_read", fn_name="trace_read_return") + File "/usr/lib/python3.9/site-packages/bcc/__init__.py", line 872, in attach_kretprobe + fn = self.load_func(fn_name, BPF.KPROBE) + File "/usr/lib/python3.9/site-packages/bcc/__init__.py", line 523, in load_func + raise Exception("Failed to load BPF program %s: %s" % +Exception: Failed to load BPF program b'trace_read_return': Permission denied +--- + tools/nfsslower.py | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/tools/nfsslower.py b/tools/nfsslower.py +index b5df8f19..682a3fb7 100755 +--- a/tools/nfsslower.py ++++ b/tools/nfsslower.py +@@ -179,8 +179,12 @@ static int trace_exit(struct pt_regs *ctx, int type) + + // populate output struct + u32 size = PT_REGS_RC(ctx); +- struct data_t data = {.type = type, .size = size, .delta_us = delta_us, +- .pid = pid}; ++ struct data_t data; ++ __builtin_memset(&data, 0, sizeof(data)); ++ data.type = type; ++ data.size = size; ++ data.delta_us = delta_us; ++ data.pid = pid; + data.ts_us = ts / 1000; + data.offset = valp->offset; + bpf_get_current_comm(&data.task, sizeof(data.task)); +-- +2.38.1 + diff --git a/bcc.spec b/bcc.spec index 42396df..a9fcf22 100644 --- a/bcc.spec +++ b/bcc.spec @@ -24,21 +24,17 @@ Name: bcc -Version: 0.24.0 -Release: 4%{?dist} +Version: 0.25.0 +Release: 1%{?dist} Summary: BPF Compiler Collection (BCC) License: ASL 2.0 URL: https://github.com/iovisor/bcc Source0: %{url}/archive/v%{version}/%{name}-%{version}.tar.gz -Patch0: %{name}-%{version}-libbpf-tools-Allow-to-use-different-cflags-for-bpf-t.patch -Patch1: %{name}-%{version}-biolatpcts-Build-fixes-on-recent-kernels.patch -Patch2: %{name}-%{version}-tools-include-blk-mq.h-in-bio-tools.patch -Patch3: %{name}-%{version}-C9S-libpbf-version-fixes.patch -Patch4: %{name}-%{version}-Revert-libbpf-1.0-changes.patch -Patch5: %{name}-%{version}-C9S-Fix-mdflush.patch -Patch6: %{name}-%{version}-biolatency-biolatpcts-biosnoop-biotop-Build-fix-for-.patch -Patch7: %{name}-%{version}-libbpf-tools-Fix-dropped-request-rq_disk-for-kernel-.patch -Patch8: %{name}-%{version}-tools-mdflush-include-blkdev.h-instead-of-genhd.h.patch +Patch0: %%{name}-%%{version}-bcc-support-building-with-external-libbpf-package-an.patch +Patch2: %%{name}-%%{version}-Fix-bpf_pseudo_fd-type-conversion-error.patch +Patch3: %%{name}-%%{version}-Fix-clang-15-int-to-pointer-conversion-errors.patch +Patch4: %%{name}-%%{version}-Fix-some-documentation-issues-4197.patch +Patch5: %%{name}-%%{version}-tools-nfsslower-fix-an-uninitialized-struct-error.patch # Arches will be included as upstream support is added and dependencies are # satisfied in the respective arches @@ -60,9 +56,9 @@ BuildRequires: ncurses-devel %if %{with lua} BuildRequires: pkgconfig(luajit) %endif -BuildRequires: libbpf-devel >= 0.6.0, libbpf-static >= 0.6.0 +BuildRequires: libbpf-devel >= 2:0.8.0, libbpf-static >= 2:0.8.0 -Requires: libbpf >= 0.6.0 +Requires: libbpf >= 2:0.8.0 Requires: tar Recommends: kernel-devel @@ -262,6 +258,10 @@ cp -a libbpf-tools/tmp-install/bin/* %{buildroot}/%{_sbindir}/ %endif %changelog +* Tue Dec 20 2022 Jerome Marchand - 0.25.0-1 +- Rebase to v0.25.0 +- Misc documentation and man pages fixes + * Tue Aug 23 2022 Jerome Marchand - 0.24.1-4 - Fix mdflush tool (rhbz#2108001) diff --git a/sources b/sources index 8bb57c2..e4aac60 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (bcc-0.24.0.tar.gz) = 951672e3a8e5ad56eedf513477317ec3d3b4cf2d594bbfce20f3d19ddf7ce255e9dcfc69d9b05bb765a16e769c8e42d7c57071ddb86fb32437f527d3d25d19b6 +SHA512 (bcc-0.25.0.tar.gz) = 9f71f6c21d1f66054985562168d5848352f5029383e9c65c907a6f044258bc23df842cc65db20bfaaf33789e69c9b8e7b606a32dc882cbdf093b71768c8b521d