mirror of
https://github.com/netdata/libbpf.git
synced 2026-03-15 05:49:07 +08:00
Compare commits
32 Commits
netdata_pa
...
v1.4.3p_ne
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d1fe77f65 | ||
|
|
fbcb2871fe | ||
|
|
61a6e8edd7 | ||
|
|
4ab7361e64 | ||
|
|
ff856238e2 | ||
|
|
c085e9c364 | ||
|
|
805b689cd2 | ||
|
|
9b789075a9 | ||
|
|
c22d662a95 | ||
|
|
074445067f | ||
|
|
9a1f1f28c6 | ||
|
|
0a519f87ee | ||
|
|
d9f9fd5b22 | ||
|
|
d4d3e68e8d | ||
|
|
0babfb126a | ||
|
|
89ed67d7ab | ||
|
|
8dfa981c53 | ||
|
|
15b461a608 | ||
|
|
ec3c369941 | ||
|
|
89aecd2188 | ||
|
|
02724cfd07 | ||
|
|
3827aa514c | ||
|
|
e5146eff75 | ||
|
|
ed54f30307 | ||
|
|
fe5fe762b9 | ||
|
|
504369cba4 | ||
|
|
ea02e10fc4 | ||
|
|
4ec5e360ae | ||
|
|
cb7bfc5e51 | ||
|
|
e3e84bd7d0 | ||
|
|
f3c4172c61 | ||
|
|
d045f7682b |
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,3 +0,0 @@
|
||||
Thank you for considering a contribution!
|
||||
|
||||
Please note that the `libbpf` authoritative source code is developed as part of bpf-next Linux source tree under tools/lib/bpf subdirectory and is periodically synced to Github. As such, all the libbpf changes should be sent to BPF mailing list, please don't open PRs here unless you are changing Github-specific parts of libbpf (e.g., Github-specific Makefile).
|
||||
189005
.github/actions/build-selftests/vmlinux.h
vendored
189005
.github/actions/build-selftests/vmlinux.h
vendored
File diff suppressed because it is too large
Load Diff
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -53,7 +53,7 @@ jobs:
|
||||
|
||||
ubuntu:
|
||||
runs-on: ubuntu-latest
|
||||
name: Ubuntu Focal Build (${{ matrix.arch }})
|
||||
name: Ubuntu Build (${{ matrix.arch }})
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -75,7 +75,7 @@ jobs:
|
||||
if: matrix.arch != 'x86'
|
||||
with:
|
||||
distro:
|
||||
ubuntu20.04
|
||||
ubuntu22.04
|
||||
arch:
|
||||
${{ matrix.arch }}
|
||||
setup:
|
||||
|
||||
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@@ -17,7 +17,7 @@ permissions:
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ matrix.language }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
2
.github/workflows/pahole.yml
vendored
2
.github/workflows/pahole.yml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
vmtest:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
name: Kernel LATEST + staging pahole
|
||||
env:
|
||||
STAGING: tmp.master
|
||||
|
||||
1
.mailmap
1
.mailmap
@@ -12,6 +12,7 @@ Leo Yan <leo.yan@linux.dev> <leo.yan@linaro.org>
|
||||
Mark Starovoytov <mstarovo@pm.me> <mstarovoitov@marvell.com>
|
||||
Maxim Mikityanskiy <maxtram95@gmail.com> <maximmi@mellanox.com>
|
||||
Maxim Mikityanskiy <maxtram95@gmail.com> <maximmi@nvidia.com>
|
||||
Puranjay Mohan <puranjay@kernel.org> <puranjay12@gmail.com>
|
||||
Quentin Monnet <qmo@kernel.org> <quentin@isovalent.com>
|
||||
Quentin Monnet <qmo@kernel.org> <quentin.monnet@netronome.com>
|
||||
Vadim Fedorenko <vadim.fedorenko@linux.dev> <vfedorenko@novek.ru>
|
||||
|
||||
@@ -1 +1 @@
|
||||
3e9bc0472b910d4115e16e9c2d684c7757cb6c60
|
||||
62da3acd28955e7299babebdfcb14243b789e773
|
||||
|
||||
@@ -1 +1 @@
|
||||
0737df6de94661ae55fd3343ce9abec32c687e62
|
||||
531876c80004ecff7bfdbd8ba6c6b48835ef5e22
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
From 0daad0a615e687e1247230f3d0c31ae60ba32314 Mon Sep 17 00:00:00 2001
|
||||
From: Andrii Nakryiko <andrii@kernel.org>
|
||||
Date: Tue, 28 May 2024 15:29:38 -0700
|
||||
Subject: [PATCH bpf-next] selftests/bpf: fix inet_csk_accept prototype in
|
||||
test_sk_storage_tracing.c
|
||||
|
||||
Recent kernel change ([0]) changed inet_csk_accept() prototype. Adapt
|
||||
progs/test_sk_storage_tracing.c to take that into account.
|
||||
|
||||
[0] 92ef0fd55ac8 ("net: change proto and proto_ops accept type")
|
||||
|
||||
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
|
||||
---
|
||||
tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c b/tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c
|
||||
index 02e718f06e0f..40531e56776e 100644
|
||||
--- a/tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c
|
||||
+++ b/tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c
|
||||
@@ -84,7 +84,7 @@ int BPF_PROG(trace_tcp_connect, struct sock *sk)
|
||||
}
|
||||
|
||||
SEC("fexit/inet_csk_accept")
|
||||
-int BPF_PROG(inet_csk_accept, struct sock *sk, int flags, int *err, bool kern,
|
||||
+int BPF_PROG(inet_csk_accept, struct sock *sk, struct proto_accept_arg *arg,
|
||||
struct sock *accepted_sk)
|
||||
{
|
||||
set_task_info(accepted_sk);
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -219,6 +219,14 @@ compilation and skeleton generation. Using Libbpf-rs will make building user
|
||||
space part of the BPF application easier. Note that the BPF program themselves
|
||||
must still be written in plain C.
|
||||
|
||||
libbpf logging
|
||||
==============
|
||||
|
||||
By default, libbpf logs informational and warning messages to stderr. The
|
||||
verbosity of these messages can be controlled by setting the environment
|
||||
variable LIBBPF_LOG_LEVEL to either warn, info, or debug. A custom log
|
||||
callback can be set using ``libbpf_set_print()``.
|
||||
|
||||
Additional Documentation
|
||||
========================
|
||||
|
||||
|
||||
@@ -6207,12 +6207,17 @@ union { \
|
||||
__u64 :64; \
|
||||
} __attribute__((aligned(8)))
|
||||
|
||||
/* The enum used in skb->tstamp_type. It specifies the clock type
|
||||
* of the time stored in the skb->tstamp.
|
||||
*/
|
||||
enum {
|
||||
BPF_SKB_TSTAMP_UNSPEC,
|
||||
BPF_SKB_TSTAMP_DELIVERY_MONO, /* tstamp has mono delivery time */
|
||||
/* For any BPF_SKB_TSTAMP_* that the bpf prog cannot handle,
|
||||
* the bpf prog should handle it like BPF_SKB_TSTAMP_UNSPEC
|
||||
* and try to deduce it by ingress, egress or skb->sk->sk_clockid.
|
||||
BPF_SKB_TSTAMP_UNSPEC = 0, /* DEPRECATED */
|
||||
BPF_SKB_TSTAMP_DELIVERY_MONO = 1, /* DEPRECATED */
|
||||
BPF_SKB_CLOCK_REALTIME = 0,
|
||||
BPF_SKB_CLOCK_MONOTONIC = 1,
|
||||
BPF_SKB_CLOCK_TAI = 2,
|
||||
/* For any future BPF_SKB_CLOCK_* that the bpf prog cannot handle,
|
||||
* the bpf prog can try to deduce it by ingress/egress/skb->sk->sk_clockid.
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI_LINUX_FCNTL_H
|
||||
#define _UAPI_LINUX_FCNTL_H
|
||||
|
||||
#include <asm/fcntl.h>
|
||||
#include <linux/openat2.h>
|
||||
|
||||
#define F_SETLEASE (F_LINUX_SPECIFIC_BASE + 0)
|
||||
#define F_GETLEASE (F_LINUX_SPECIFIC_BASE + 1)
|
||||
|
||||
/*
|
||||
* Cancel a blocking posix lock; internal use only until we expose an
|
||||
* asynchronous lock api to userspace:
|
||||
*/
|
||||
#define F_CANCELLK (F_LINUX_SPECIFIC_BASE + 5)
|
||||
|
||||
/* Create a file descriptor with FD_CLOEXEC set. */
|
||||
#define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
|
||||
|
||||
/*
|
||||
* Request nofications on a directory.
|
||||
* See below for events that may be notified.
|
||||
*/
|
||||
#define F_NOTIFY (F_LINUX_SPECIFIC_BASE+2)
|
||||
|
||||
/*
|
||||
* Set and get of pipe page size array
|
||||
*/
|
||||
#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
|
||||
#define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
|
||||
|
||||
/*
|
||||
* Set/Get seals
|
||||
*/
|
||||
#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
|
||||
#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
|
||||
|
||||
/*
|
||||
* Types of seals
|
||||
*/
|
||||
#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
|
||||
#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
|
||||
#define F_SEAL_GROW 0x0004 /* prevent file from growing */
|
||||
#define F_SEAL_WRITE 0x0008 /* prevent writes */
|
||||
#define F_SEAL_FUTURE_WRITE 0x0010 /* prevent future writes while mapped */
|
||||
#define F_SEAL_EXEC 0x0020 /* prevent chmod modifying exec bits */
|
||||
/* (1U << 31) is reserved for signed error codes */
|
||||
|
||||
/*
|
||||
* Set/Get write life time hints. {GET,SET}_RW_HINT operate on the
|
||||
* underlying inode, while {GET,SET}_FILE_RW_HINT operate only on
|
||||
* the specific file.
|
||||
*/
|
||||
#define F_GET_RW_HINT (F_LINUX_SPECIFIC_BASE + 11)
|
||||
#define F_SET_RW_HINT (F_LINUX_SPECIFIC_BASE + 12)
|
||||
#define F_GET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 13)
|
||||
#define F_SET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 14)
|
||||
|
||||
/*
|
||||
* Valid hint values for F_{GET,SET}_RW_HINT. 0 is "not set", or can be
|
||||
* used to clear any hints previously set.
|
||||
*/
|
||||
#define RWH_WRITE_LIFE_NOT_SET 0
|
||||
#define RWH_WRITE_LIFE_NONE 1
|
||||
#define RWH_WRITE_LIFE_SHORT 2
|
||||
#define RWH_WRITE_LIFE_MEDIUM 3
|
||||
#define RWH_WRITE_LIFE_LONG 4
|
||||
#define RWH_WRITE_LIFE_EXTREME 5
|
||||
|
||||
/*
|
||||
* The originally introduced spelling is remained from the first
|
||||
* versions of the patch set that introduced the feature, see commit
|
||||
* v4.13-rc1~212^2~51.
|
||||
*/
|
||||
#define RWF_WRITE_LIFE_NOT_SET RWH_WRITE_LIFE_NOT_SET
|
||||
|
||||
/*
|
||||
* Types of directory notifications that may be requested.
|
||||
*/
|
||||
#define DN_ACCESS 0x00000001 /* File accessed */
|
||||
#define DN_MODIFY 0x00000002 /* File modified */
|
||||
#define DN_CREATE 0x00000004 /* File created */
|
||||
#define DN_DELETE 0x00000008 /* File removed */
|
||||
#define DN_RENAME 0x00000010 /* File renamed */
|
||||
#define DN_ATTRIB 0x00000020 /* File changed attibutes */
|
||||
#define DN_MULTISHOT 0x80000000 /* Don't remove notifier */
|
||||
|
||||
/*
|
||||
* The constants AT_REMOVEDIR and AT_EACCESS have the same value. AT_EACCESS is
|
||||
* meaningful only to faccessat, while AT_REMOVEDIR is meaningful only to
|
||||
* unlinkat. The two functions do completely different things and therefore,
|
||||
* the flags can be allowed to overlap. For example, passing AT_REMOVEDIR to
|
||||
* faccessat would be undefined behavior and thus treating it equivalent to
|
||||
* AT_EACCESS is valid undefined behavior.
|
||||
*/
|
||||
#define AT_FDCWD -100 /* Special value used to indicate
|
||||
openat should use the current
|
||||
working directory. */
|
||||
#define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links. */
|
||||
#define AT_EACCESS 0x200 /* Test access permitted for
|
||||
effective IDs, not real IDs. */
|
||||
#define AT_REMOVEDIR 0x200 /* Remove directory instead of
|
||||
unlinking file. */
|
||||
#define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */
|
||||
#define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount traversal */
|
||||
#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */
|
||||
|
||||
#define AT_STATX_SYNC_TYPE 0x6000 /* Type of synchronisation required from statx() */
|
||||
#define AT_STATX_SYNC_AS_STAT 0x0000 /* - Do whatever stat() does */
|
||||
#define AT_STATX_FORCE_SYNC 0x2000 /* - Force the attributes to be sync'd with the server */
|
||||
#define AT_STATX_DONT_SYNC 0x4000 /* - Don't sync attributes with the server */
|
||||
|
||||
#define AT_RECURSIVE 0x8000 /* Apply to the entire subtree */
|
||||
|
||||
/* Flags for name_to_handle_at(2). We reuse AT_ flag space to save bits... */
|
||||
#define AT_HANDLE_FID AT_REMOVEDIR /* file handle is needed to
|
||||
compare object identity and may not
|
||||
be usable to open_by_handle_at(2) */
|
||||
#if defined(__KERNEL__)
|
||||
#define AT_GETATTR_NOSEC 0x80000000
|
||||
#endif
|
||||
|
||||
#endif /* _UAPI_LINUX_FCNTL_H */
|
||||
@@ -146,6 +146,28 @@ enum {
|
||||
NETDEV_A_QSTATS_TX_PACKETS,
|
||||
NETDEV_A_QSTATS_TX_BYTES,
|
||||
NETDEV_A_QSTATS_RX_ALLOC_FAIL,
|
||||
NETDEV_A_QSTATS_RX_HW_DROPS,
|
||||
NETDEV_A_QSTATS_RX_HW_DROP_OVERRUNS,
|
||||
NETDEV_A_QSTATS_RX_CSUM_COMPLETE,
|
||||
NETDEV_A_QSTATS_RX_CSUM_UNNECESSARY,
|
||||
NETDEV_A_QSTATS_RX_CSUM_NONE,
|
||||
NETDEV_A_QSTATS_RX_CSUM_BAD,
|
||||
NETDEV_A_QSTATS_RX_HW_GRO_PACKETS,
|
||||
NETDEV_A_QSTATS_RX_HW_GRO_BYTES,
|
||||
NETDEV_A_QSTATS_RX_HW_GRO_WIRE_PACKETS,
|
||||
NETDEV_A_QSTATS_RX_HW_GRO_WIRE_BYTES,
|
||||
NETDEV_A_QSTATS_RX_HW_DROP_RATELIMITS,
|
||||
NETDEV_A_QSTATS_TX_HW_DROPS,
|
||||
NETDEV_A_QSTATS_TX_HW_DROP_ERRORS,
|
||||
NETDEV_A_QSTATS_TX_CSUM_NONE,
|
||||
NETDEV_A_QSTATS_TX_NEEDS_CSUM,
|
||||
NETDEV_A_QSTATS_TX_HW_GSO_PACKETS,
|
||||
NETDEV_A_QSTATS_TX_HW_GSO_BYTES,
|
||||
NETDEV_A_QSTATS_TX_HW_GSO_WIRE_PACKETS,
|
||||
NETDEV_A_QSTATS_TX_HW_GSO_WIRE_BYTES,
|
||||
NETDEV_A_QSTATS_TX_HW_DROP_RATELIMITS,
|
||||
NETDEV_A_QSTATS_TX_STOP,
|
||||
NETDEV_A_QSTATS_TX_WAKE,
|
||||
|
||||
__NETDEV_A_QSTATS_MAX,
|
||||
NETDEV_A_QSTATS_MAX = (__NETDEV_A_QSTATS_MAX - 1)
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI_LINUX_OPENAT2_H
|
||||
#define _UAPI_LINUX_OPENAT2_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* Arguments for how openat2(2) should open the target path. If only @flags and
|
||||
* @mode are non-zero, then openat2(2) operates very similarly to openat(2).
|
||||
*
|
||||
* However, unlike openat(2), unknown or invalid bits in @flags result in
|
||||
* -EINVAL rather than being silently ignored. @mode must be zero unless one of
|
||||
* {O_CREAT, O_TMPFILE} are set.
|
||||
*
|
||||
* @flags: O_* flags.
|
||||
* @mode: O_CREAT/O_TMPFILE file mode.
|
||||
* @resolve: RESOLVE_* flags.
|
||||
*/
|
||||
struct open_how {
|
||||
__u64 flags;
|
||||
__u64 mode;
|
||||
__u64 resolve;
|
||||
};
|
||||
|
||||
/* how->resolve flags for openat2(2). */
|
||||
#define RESOLVE_NO_XDEV 0x01 /* Block mount-point crossings
|
||||
(includes bind-mounts). */
|
||||
#define RESOLVE_NO_MAGICLINKS 0x02 /* Block traversal through procfs-style
|
||||
"magic-links". */
|
||||
#define RESOLVE_NO_SYMLINKS 0x04 /* Block traversal through all symlinks
|
||||
(implies OEXT_NO_MAGICLINKS) */
|
||||
#define RESOLVE_BENEATH 0x08 /* Block "lexical" trickery like
|
||||
"..", symlinks, and absolute
|
||||
paths which escape the dirfd. */
|
||||
#define RESOLVE_IN_ROOT 0x10 /* Make all jumps to "/" and ".."
|
||||
be scoped inside the dirfd
|
||||
(similar to chroot(2)). */
|
||||
#define RESOLVE_CACHED 0x20 /* Only complete if resolution can be
|
||||
completed through cached lookup. May
|
||||
return -EAGAIN if that's not
|
||||
possible. */
|
||||
|
||||
#endif /* _UAPI_LINUX_OPENAT2_H */
|
||||
@@ -105,7 +105,7 @@ int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts)
|
||||
*/
|
||||
int probe_memcg_account(int token_fd)
|
||||
{
|
||||
const size_t attr_sz = offsetofend(union bpf_attr, attach_btf_obj_fd);
|
||||
const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd);
|
||||
struct bpf_insn insns[] = {
|
||||
BPF_EMIT_CALL(BPF_FUNC_ktime_get_coarse_ns),
|
||||
BPF_EXIT_INSN(),
|
||||
|
||||
@@ -104,6 +104,7 @@ enum bpf_enum_value_kind {
|
||||
case 2: val = *(const unsigned short *)p; break; \
|
||||
case 4: val = *(const unsigned int *)p; break; \
|
||||
case 8: val = *(const unsigned long long *)p; break; \
|
||||
default: val = 0; break; \
|
||||
} \
|
||||
val <<= __CORE_RELO(s, field, LSHIFT_U64); \
|
||||
if (__CORE_RELO(s, field, SIGNED)) \
|
||||
|
||||
@@ -186,10 +186,21 @@ enum libbpf_tristate {
|
||||
#define __kptr __attribute__((btf_type_tag("kptr")))
|
||||
#define __percpu_kptr __attribute__((btf_type_tag("percpu_kptr")))
|
||||
|
||||
#define bpf_ksym_exists(sym) ({ \
|
||||
_Static_assert(!__builtin_constant_p(!!sym), #sym " should be marked as __weak"); \
|
||||
!!sym; \
|
||||
#if defined (__clang__)
|
||||
#define bpf_ksym_exists(sym) ({ \
|
||||
_Static_assert(!__builtin_constant_p(!!sym), \
|
||||
#sym " should be marked as __weak"); \
|
||||
!!sym; \
|
||||
})
|
||||
#elif __GNUC__ > 8
|
||||
#define bpf_ksym_exists(sym) ({ \
|
||||
_Static_assert(__builtin_has_attribute (*sym, __weak__), \
|
||||
#sym " should be marked as __weak"); \
|
||||
!!sym; \
|
||||
})
|
||||
#else
|
||||
#define bpf_ksym_exists(sym) !!sym
|
||||
#endif
|
||||
|
||||
#define __arg_ctx __attribute__((btf_decl_tag("arg:ctx")))
|
||||
#define __arg_nonnull __attribute((btf_decl_tag("arg:nonnull")))
|
||||
|
||||
@@ -633,18 +633,18 @@ struct pt_regs;
|
||||
#endif
|
||||
|
||||
#define ___bpf_ctx_cast0() ctx
|
||||
#define ___bpf_ctx_cast1(x) ___bpf_ctx_cast0(), (void *)ctx[0]
|
||||
#define ___bpf_ctx_cast2(x, args...) ___bpf_ctx_cast1(args), (void *)ctx[1]
|
||||
#define ___bpf_ctx_cast3(x, args...) ___bpf_ctx_cast2(args), (void *)ctx[2]
|
||||
#define ___bpf_ctx_cast4(x, args...) ___bpf_ctx_cast3(args), (void *)ctx[3]
|
||||
#define ___bpf_ctx_cast5(x, args...) ___bpf_ctx_cast4(args), (void *)ctx[4]
|
||||
#define ___bpf_ctx_cast6(x, args...) ___bpf_ctx_cast5(args), (void *)ctx[5]
|
||||
#define ___bpf_ctx_cast7(x, args...) ___bpf_ctx_cast6(args), (void *)ctx[6]
|
||||
#define ___bpf_ctx_cast8(x, args...) ___bpf_ctx_cast7(args), (void *)ctx[7]
|
||||
#define ___bpf_ctx_cast9(x, args...) ___bpf_ctx_cast8(args), (void *)ctx[8]
|
||||
#define ___bpf_ctx_cast10(x, args...) ___bpf_ctx_cast9(args), (void *)ctx[9]
|
||||
#define ___bpf_ctx_cast11(x, args...) ___bpf_ctx_cast10(args), (void *)ctx[10]
|
||||
#define ___bpf_ctx_cast12(x, args...) ___bpf_ctx_cast11(args), (void *)ctx[11]
|
||||
#define ___bpf_ctx_cast1(x) ___bpf_ctx_cast0(), ctx[0]
|
||||
#define ___bpf_ctx_cast2(x, args...) ___bpf_ctx_cast1(args), ctx[1]
|
||||
#define ___bpf_ctx_cast3(x, args...) ___bpf_ctx_cast2(args), ctx[2]
|
||||
#define ___bpf_ctx_cast4(x, args...) ___bpf_ctx_cast3(args), ctx[3]
|
||||
#define ___bpf_ctx_cast5(x, args...) ___bpf_ctx_cast4(args), ctx[4]
|
||||
#define ___bpf_ctx_cast6(x, args...) ___bpf_ctx_cast5(args), ctx[5]
|
||||
#define ___bpf_ctx_cast7(x, args...) ___bpf_ctx_cast6(args), ctx[6]
|
||||
#define ___bpf_ctx_cast8(x, args...) ___bpf_ctx_cast7(args), ctx[7]
|
||||
#define ___bpf_ctx_cast9(x, args...) ___bpf_ctx_cast8(args), ctx[8]
|
||||
#define ___bpf_ctx_cast10(x, args...) ___bpf_ctx_cast9(args), ctx[9]
|
||||
#define ___bpf_ctx_cast11(x, args...) ___bpf_ctx_cast10(args), ctx[10]
|
||||
#define ___bpf_ctx_cast12(x, args...) ___bpf_ctx_cast11(args), ctx[11]
|
||||
#define ___bpf_ctx_cast(args...) ___bpf_apply(___bpf_ctx_cast, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
@@ -786,14 +786,14 @@ ____##name(unsigned long long *ctx ___bpf_ctx_decl(args))
|
||||
struct pt_regs;
|
||||
|
||||
#define ___bpf_kprobe_args0() ctx
|
||||
#define ___bpf_kprobe_args1(x) ___bpf_kprobe_args0(), (void *)PT_REGS_PARM1(ctx)
|
||||
#define ___bpf_kprobe_args2(x, args...) ___bpf_kprobe_args1(args), (void *)PT_REGS_PARM2(ctx)
|
||||
#define ___bpf_kprobe_args3(x, args...) ___bpf_kprobe_args2(args), (void *)PT_REGS_PARM3(ctx)
|
||||
#define ___bpf_kprobe_args4(x, args...) ___bpf_kprobe_args3(args), (void *)PT_REGS_PARM4(ctx)
|
||||
#define ___bpf_kprobe_args5(x, args...) ___bpf_kprobe_args4(args), (void *)PT_REGS_PARM5(ctx)
|
||||
#define ___bpf_kprobe_args6(x, args...) ___bpf_kprobe_args5(args), (void *)PT_REGS_PARM6(ctx)
|
||||
#define ___bpf_kprobe_args7(x, args...) ___bpf_kprobe_args6(args), (void *)PT_REGS_PARM7(ctx)
|
||||
#define ___bpf_kprobe_args8(x, args...) ___bpf_kprobe_args7(args), (void *)PT_REGS_PARM8(ctx)
|
||||
#define ___bpf_kprobe_args1(x) ___bpf_kprobe_args0(), (unsigned long long)PT_REGS_PARM1(ctx)
|
||||
#define ___bpf_kprobe_args2(x, args...) ___bpf_kprobe_args1(args), (unsigned long long)PT_REGS_PARM2(ctx)
|
||||
#define ___bpf_kprobe_args3(x, args...) ___bpf_kprobe_args2(args), (unsigned long long)PT_REGS_PARM3(ctx)
|
||||
#define ___bpf_kprobe_args4(x, args...) ___bpf_kprobe_args3(args), (unsigned long long)PT_REGS_PARM4(ctx)
|
||||
#define ___bpf_kprobe_args5(x, args...) ___bpf_kprobe_args4(args), (unsigned long long)PT_REGS_PARM5(ctx)
|
||||
#define ___bpf_kprobe_args6(x, args...) ___bpf_kprobe_args5(args), (unsigned long long)PT_REGS_PARM6(ctx)
|
||||
#define ___bpf_kprobe_args7(x, args...) ___bpf_kprobe_args6(args), (unsigned long long)PT_REGS_PARM7(ctx)
|
||||
#define ___bpf_kprobe_args8(x, args...) ___bpf_kprobe_args7(args), (unsigned long long)PT_REGS_PARM8(ctx)
|
||||
#define ___bpf_kprobe_args(args...) ___bpf_apply(___bpf_kprobe_args, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
@@ -821,7 +821,7 @@ static __always_inline typeof(name(0)) \
|
||||
____##name(struct pt_regs *ctx, ##args)
|
||||
|
||||
#define ___bpf_kretprobe_args0() ctx
|
||||
#define ___bpf_kretprobe_args1(x) ___bpf_kretprobe_args0(), (void *)PT_REGS_RC(ctx)
|
||||
#define ___bpf_kretprobe_args1(x) ___bpf_kretprobe_args0(), (unsigned long long)PT_REGS_RC(ctx)
|
||||
#define ___bpf_kretprobe_args(args...) ___bpf_apply(___bpf_kretprobe_args, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
@@ -845,24 +845,24 @@ static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)
|
||||
|
||||
/* If kernel has CONFIG_ARCH_HAS_SYSCALL_WRAPPER, read pt_regs directly */
|
||||
#define ___bpf_syscall_args0() ctx
|
||||
#define ___bpf_syscall_args1(x) ___bpf_syscall_args0(), (void *)PT_REGS_PARM1_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args2(x, args...) ___bpf_syscall_args1(args), (void *)PT_REGS_PARM2_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args3(x, args...) ___bpf_syscall_args2(args), (void *)PT_REGS_PARM3_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args4(x, args...) ___bpf_syscall_args3(args), (void *)PT_REGS_PARM4_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args5(x, args...) ___bpf_syscall_args4(args), (void *)PT_REGS_PARM5_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args6(x, args...) ___bpf_syscall_args5(args), (void *)PT_REGS_PARM6_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args7(x, args...) ___bpf_syscall_args6(args), (void *)PT_REGS_PARM7_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args1(x) ___bpf_syscall_args0(), (unsigned long long)PT_REGS_PARM1_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args2(x, args...) ___bpf_syscall_args1(args), (unsigned long long)PT_REGS_PARM2_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args3(x, args...) ___bpf_syscall_args2(args), (unsigned long long)PT_REGS_PARM3_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args4(x, args...) ___bpf_syscall_args3(args), (unsigned long long)PT_REGS_PARM4_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args5(x, args...) ___bpf_syscall_args4(args), (unsigned long long)PT_REGS_PARM5_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args6(x, args...) ___bpf_syscall_args5(args), (unsigned long long)PT_REGS_PARM6_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args7(x, args...) ___bpf_syscall_args6(args), (unsigned long long)PT_REGS_PARM7_SYSCALL(regs)
|
||||
#define ___bpf_syscall_args(args...) ___bpf_apply(___bpf_syscall_args, ___bpf_narg(args))(args)
|
||||
|
||||
/* If kernel doesn't have CONFIG_ARCH_HAS_SYSCALL_WRAPPER, we have to BPF_CORE_READ from pt_regs */
|
||||
#define ___bpf_syswrap_args0() ctx
|
||||
#define ___bpf_syswrap_args1(x) ___bpf_syswrap_args0(), (void *)PT_REGS_PARM1_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args2(x, args...) ___bpf_syswrap_args1(args), (void *)PT_REGS_PARM2_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args3(x, args...) ___bpf_syswrap_args2(args), (void *)PT_REGS_PARM3_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args4(x, args...) ___bpf_syswrap_args3(args), (void *)PT_REGS_PARM4_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args5(x, args...) ___bpf_syswrap_args4(args), (void *)PT_REGS_PARM5_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args6(x, args...) ___bpf_syswrap_args5(args), (void *)PT_REGS_PARM6_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args7(x, args...) ___bpf_syswrap_args6(args), (void *)PT_REGS_PARM7_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args1(x) ___bpf_syswrap_args0(), (unsigned long long)PT_REGS_PARM1_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args2(x, args...) ___bpf_syswrap_args1(args), (unsigned long long)PT_REGS_PARM2_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args3(x, args...) ___bpf_syswrap_args2(args), (unsigned long long)PT_REGS_PARM3_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args4(x, args...) ___bpf_syswrap_args3(args), (unsigned long long)PT_REGS_PARM4_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args5(x, args...) ___bpf_syswrap_args4(args), (unsigned long long)PT_REGS_PARM5_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args6(x, args...) ___bpf_syswrap_args5(args), (unsigned long long)PT_REGS_PARM6_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args7(x, args...) ___bpf_syswrap_args6(args), (unsigned long long)PT_REGS_PARM7_CORE_SYSCALL(regs)
|
||||
#define ___bpf_syswrap_args(args...) ___bpf_apply(___bpf_syswrap_args, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
|
||||
@@ -22,7 +22,7 @@ int probe_fd(int fd)
|
||||
|
||||
static int probe_kern_prog_name(int token_fd)
|
||||
{
|
||||
const size_t attr_sz = offsetofend(union bpf_attr, prog_name);
|
||||
const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd);
|
||||
struct bpf_insn insns[] = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
@@ -392,11 +392,41 @@ static int probe_uprobe_multi_link(int token_fd)
|
||||
link_fd = bpf_link_create(prog_fd, -1, BPF_TRACE_UPROBE_MULTI, &link_opts);
|
||||
err = -errno; /* close() can clobber errno */
|
||||
|
||||
if (link_fd >= 0 || err != -EBADF) {
|
||||
if (link_fd >= 0)
|
||||
close(link_fd);
|
||||
close(prog_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initial multi-uprobe support in kernel didn't handle PID filtering
|
||||
* correctly (it was doing thread filtering, not process filtering).
|
||||
* So now we'll detect if PID filtering logic was fixed, and, if not,
|
||||
* we'll pretend multi-uprobes are not supported, if not.
|
||||
* Multi-uprobes are used in USDT attachment logic, and we need to be
|
||||
* conservative here, because multi-uprobe selection happens early at
|
||||
* load time, while the use of PID filtering is known late at
|
||||
* attachment time, at which point it's too late to undo multi-uprobe
|
||||
* selection.
|
||||
*
|
||||
* Creating uprobe with pid == -1 for (invalid) '/' binary will fail
|
||||
* early with -EINVAL on kernels with fixed PID filtering logic;
|
||||
* otherwise -ESRCH would be returned if passed correct binary path
|
||||
* (but we'll just get -BADF, of course).
|
||||
*/
|
||||
link_opts.uprobe_multi.pid = -1; /* invalid PID */
|
||||
link_opts.uprobe_multi.path = "/"; /* invalid path */
|
||||
link_opts.uprobe_multi.offsets = &offset;
|
||||
link_opts.uprobe_multi.cnt = 1;
|
||||
|
||||
link_fd = bpf_link_create(prog_fd, -1, BPF_TRACE_UPROBE_MULTI, &link_opts);
|
||||
err = -errno; /* close() can clobber errno */
|
||||
|
||||
if (link_fd >= 0)
|
||||
close(link_fd);
|
||||
close(prog_fd);
|
||||
|
||||
return link_fd < 0 && err == -EBADF;
|
||||
return link_fd < 0 && err == -EINVAL;
|
||||
}
|
||||
|
||||
static int probe_kern_bpf_cookie(int token_fd)
|
||||
|
||||
67
src/libbpf.c
67
src/libbpf.c
@@ -229,7 +229,30 @@ static const char * const prog_type_name[] = {
|
||||
static int __base_pr(enum libbpf_print_level level, const char *format,
|
||||
va_list args)
|
||||
{
|
||||
if (level == LIBBPF_DEBUG)
|
||||
const char *env_var = "LIBBPF_LOG_LEVEL";
|
||||
static enum libbpf_print_level min_level = LIBBPF_INFO;
|
||||
static bool initialized;
|
||||
|
||||
if (!initialized) {
|
||||
char *verbosity;
|
||||
|
||||
initialized = true;
|
||||
verbosity = getenv(env_var);
|
||||
if (verbosity) {
|
||||
if (strcasecmp(verbosity, "warn") == 0)
|
||||
min_level = LIBBPF_WARN;
|
||||
else if (strcasecmp(verbosity, "debug") == 0)
|
||||
min_level = LIBBPF_DEBUG;
|
||||
else if (strcasecmp(verbosity, "info") == 0)
|
||||
min_level = LIBBPF_INFO;
|
||||
else
|
||||
fprintf(stderr, "libbpf: unrecognized '%s' envvar value: '%s', should be one of 'warn', 'debug', or 'info'.\n",
|
||||
env_var, verbosity);
|
||||
}
|
||||
}
|
||||
|
||||
/* if too verbose, skip logging */
|
||||
if (level > min_level)
|
||||
return 0;
|
||||
|
||||
return vfprintf(stderr, format, args);
|
||||
@@ -1152,22 +1175,15 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map)
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
prog = st_ops->progs[i];
|
||||
if (prog) {
|
||||
if (st_ops->progs[i]) {
|
||||
/* If we had declaratively set struct_ops callback, we need to
|
||||
* first validate that it's actually a struct_ops program.
|
||||
* And then force its autoload to false, because it doesn't have
|
||||
* force its autoload to false, because it doesn't have
|
||||
* a chance of succeeding from POV of the current struct_ops map.
|
||||
* If this program is still referenced somewhere else, though,
|
||||
* then bpf_object_adjust_struct_ops_autoload() will update its
|
||||
* autoload accordingly.
|
||||
*/
|
||||
if (!is_valid_st_ops_program(obj, prog)) {
|
||||
pr_warn("struct_ops init_kern %s: member %s is declaratively assigned a non-struct_ops program\n",
|
||||
map->name, mname);
|
||||
return -EINVAL;
|
||||
}
|
||||
prog->autoload = false;
|
||||
st_ops->progs[i]->autoload = false;
|
||||
st_ops->progs[i] = NULL;
|
||||
}
|
||||
|
||||
@@ -1200,11 +1216,19 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map)
|
||||
}
|
||||
|
||||
if (btf_is_ptr(mtype)) {
|
||||
/* Update the value from the shadow type */
|
||||
prog = *(void **)mdata;
|
||||
/* just like for !kern_member case above, reset declaratively
|
||||
* set (at compile time) program's autload to false,
|
||||
* if user replaced it with another program or NULL
|
||||
*/
|
||||
if (st_ops->progs[i] && st_ops->progs[i] != prog)
|
||||
st_ops->progs[i]->autoload = false;
|
||||
|
||||
/* Update the value from the shadow type */
|
||||
st_ops->progs[i] = prog;
|
||||
if (!prog)
|
||||
continue;
|
||||
|
||||
if (!is_valid_st_ops_program(obj, prog)) {
|
||||
pr_warn("struct_ops init_kern %s: member %s is not a struct_ops program\n",
|
||||
map->name, mname);
|
||||
@@ -7371,7 +7395,11 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog
|
||||
__u32 log_level = prog->log_level;
|
||||
int ret, err;
|
||||
|
||||
if (prog->type == BPF_PROG_TYPE_UNSPEC) {
|
||||
/* Be more helpful by rejecting programs that can't be validated early
|
||||
* with more meaningful and actionable error message.
|
||||
*/
|
||||
switch (prog->type) {
|
||||
case BPF_PROG_TYPE_UNSPEC:
|
||||
/*
|
||||
* The program type must be set. Most likely we couldn't find a proper
|
||||
* section definition at load time, and thus we didn't infer the type.
|
||||
@@ -7379,6 +7407,15 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog
|
||||
pr_warn("prog '%s': missing BPF prog type, check ELF section name '%s'\n",
|
||||
prog->name, prog->sec_name);
|
||||
return -EINVAL;
|
||||
case BPF_PROG_TYPE_STRUCT_OPS:
|
||||
if (prog->attach_btf_id == 0) {
|
||||
pr_warn("prog '%s': SEC(\"struct_ops\") program isn't referenced anywhere, did you forget to use it?\n",
|
||||
prog->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!insns || !insns_cnt)
|
||||
@@ -11579,7 +11616,7 @@ static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, stru
|
||||
|
||||
n = sscanf(spec, "%m[a-zA-Z0-9_.*?]", &pattern);
|
||||
if (n < 1) {
|
||||
pr_warn("kprobe multi pattern is invalid: %s\n", pattern);
|
||||
pr_warn("kprobe multi pattern is invalid: %s\n", spec);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -11605,7 +11642,7 @@ static int attach_kprobe_session(const struct bpf_program *prog, long cookie,
|
||||
spec = prog->sec_name + sizeof("kprobe.session/") - 1;
|
||||
n = sscanf(spec, "%m[a-zA-Z0-9_.*?]", &pattern);
|
||||
if (n < 1) {
|
||||
pr_warn("kprobe session pattern is invalid: %s\n", pattern);
|
||||
pr_warn("kprobe session pattern is invalid: %s\n", spec);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,10 @@ typedef int (*libbpf_print_fn_t)(enum libbpf_print_level level,
|
||||
|
||||
/**
|
||||
* @brief **libbpf_set_print()** sets user-provided log callback function to
|
||||
* be used for libbpf warnings and informational messages.
|
||||
* be used for libbpf warnings and informational messages. If the user callback
|
||||
* is not set, messages are logged to stderr by default. The verbosity of these
|
||||
* messages can be controlled by setting the environment variable
|
||||
* LIBBPF_LOG_LEVEL to either warn, info, or debug.
|
||||
* @param fn The log print function. If NULL, libbpf won't print anything.
|
||||
* @return Pointer to old print function.
|
||||
*
|
||||
|
||||
@@ -597,13 +597,9 @@ static inline int ensure_good_fd(int fd)
|
||||
return fd;
|
||||
}
|
||||
|
||||
static inline int sys_dup2(int oldfd, int newfd)
|
||||
static inline int sys_dup3(int oldfd, int newfd, int flags)
|
||||
{
|
||||
#ifdef __NR_dup2
|
||||
return syscall(__NR_dup2, oldfd, newfd);
|
||||
#else
|
||||
return syscall(__NR_dup3, oldfd, newfd, 0);
|
||||
#endif
|
||||
return syscall(__NR_dup3, oldfd, newfd, flags);
|
||||
}
|
||||
|
||||
/* Point *fixed_fd* to the same file that *tmp_fd* points to.
|
||||
@@ -614,7 +610,7 @@ static inline int reuse_fd(int fixed_fd, int tmp_fd)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = sys_dup2(tmp_fd, fixed_fd);
|
||||
err = sys_dup3(tmp_fd, fixed_fd, O_CLOEXEC);
|
||||
err = err < 0 ? -errno : 0;
|
||||
close(tmp_fd); /* clean up temporary FD */
|
||||
return err;
|
||||
|
||||
@@ -97,9 +97,6 @@ __u32 get_kernel_version(void)
|
||||
if (sscanf(info.release, "%u.%u.%u", &major, &minor, &patch) != 3)
|
||||
return 0;
|
||||
|
||||
if (major == 4 && minor == 19 && patch > 255)
|
||||
return KERNEL_VERSION(major, minor, 255);;
|
||||
|
||||
return KERNEL_VERSION(major, minor, patch);
|
||||
}
|
||||
|
||||
|
||||
@@ -301,7 +301,7 @@ int ring_buffer__consume_n(struct ring_buffer *rb, size_t n)
|
||||
if (n == 0)
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
return res > INT_MAX ? INT_MAX : res;
|
||||
}
|
||||
|
||||
/* Consume available ring buffer(s) data without event polling.
|
||||
@@ -405,7 +405,7 @@ int ring__map_fd(const struct ring *r)
|
||||
|
||||
int ring__consume_n(struct ring *r, size_t n)
|
||||
{
|
||||
int res;
|
||||
int64_t res;
|
||||
|
||||
res = ringbuf_process_ring(r, n);
|
||||
if (res < 0)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#undef _GNU_SOURCE
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "str_error.h"
|
||||
|
||||
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||
@@ -15,7 +16,18 @@
|
||||
char *libbpf_strerror_r(int err, char *dst, int len)
|
||||
{
|
||||
int ret = strerror_r(err < 0 ? -err : err, dst, len);
|
||||
if (ret)
|
||||
snprintf(dst, len, "ERROR: strerror_r(%d)=%d", err, ret);
|
||||
/* on glibc <2.13, ret == -1 and errno is set, if strerror_r() can't
|
||||
* handle the error, on glibc >=2.13 *positive* (errno-like) error
|
||||
* code is returned directly
|
||||
*/
|
||||
if (ret == -1)
|
||||
ret = errno;
|
||||
if (ret) {
|
||||
if (ret == EINVAL)
|
||||
/* strerror_r() doesn't recognize this specific error */
|
||||
snprintf(dst, len, "unknown error (%d)", err < 0 ? err : -err);
|
||||
else
|
||||
snprintf(dst, len, "ERROR: strerror_r(%d)=%d", err, ret);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
@@ -214,18 +214,18 @@ long bpf_usdt_cookie(struct pt_regs *ctx)
|
||||
|
||||
/* we rely on ___bpf_apply() and ___bpf_narg() macros already defined in bpf_tracing.h */
|
||||
#define ___bpf_usdt_args0() ctx
|
||||
#define ___bpf_usdt_args1(x) ___bpf_usdt_args0(), ({ long _x; bpf_usdt_arg(ctx, 0, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args2(x, args...) ___bpf_usdt_args1(args), ({ long _x; bpf_usdt_arg(ctx, 1, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args3(x, args...) ___bpf_usdt_args2(args), ({ long _x; bpf_usdt_arg(ctx, 2, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args4(x, args...) ___bpf_usdt_args3(args), ({ long _x; bpf_usdt_arg(ctx, 3, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args5(x, args...) ___bpf_usdt_args4(args), ({ long _x; bpf_usdt_arg(ctx, 4, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args6(x, args...) ___bpf_usdt_args5(args), ({ long _x; bpf_usdt_arg(ctx, 5, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args7(x, args...) ___bpf_usdt_args6(args), ({ long _x; bpf_usdt_arg(ctx, 6, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args8(x, args...) ___bpf_usdt_args7(args), ({ long _x; bpf_usdt_arg(ctx, 7, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args9(x, args...) ___bpf_usdt_args8(args), ({ long _x; bpf_usdt_arg(ctx, 8, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args10(x, args...) ___bpf_usdt_args9(args), ({ long _x; bpf_usdt_arg(ctx, 9, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args11(x, args...) ___bpf_usdt_args10(args), ({ long _x; bpf_usdt_arg(ctx, 10, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args12(x, args...) ___bpf_usdt_args11(args), ({ long _x; bpf_usdt_arg(ctx, 11, &_x); (void *)_x; })
|
||||
#define ___bpf_usdt_args1(x) ___bpf_usdt_args0(), ({ long _x; bpf_usdt_arg(ctx, 0, &_x); _x; })
|
||||
#define ___bpf_usdt_args2(x, args...) ___bpf_usdt_args1(args), ({ long _x; bpf_usdt_arg(ctx, 1, &_x); _x; })
|
||||
#define ___bpf_usdt_args3(x, args...) ___bpf_usdt_args2(args), ({ long _x; bpf_usdt_arg(ctx, 2, &_x); _x; })
|
||||
#define ___bpf_usdt_args4(x, args...) ___bpf_usdt_args3(args), ({ long _x; bpf_usdt_arg(ctx, 3, &_x); _x; })
|
||||
#define ___bpf_usdt_args5(x, args...) ___bpf_usdt_args4(args), ({ long _x; bpf_usdt_arg(ctx, 4, &_x); _x; })
|
||||
#define ___bpf_usdt_args6(x, args...) ___bpf_usdt_args5(args), ({ long _x; bpf_usdt_arg(ctx, 5, &_x); _x; })
|
||||
#define ___bpf_usdt_args7(x, args...) ___bpf_usdt_args6(args), ({ long _x; bpf_usdt_arg(ctx, 6, &_x); _x; })
|
||||
#define ___bpf_usdt_args8(x, args...) ___bpf_usdt_args7(args), ({ long _x; bpf_usdt_arg(ctx, 7, &_x); _x; })
|
||||
#define ___bpf_usdt_args9(x, args...) ___bpf_usdt_args8(args), ({ long _x; bpf_usdt_arg(ctx, 8, &_x); _x; })
|
||||
#define ___bpf_usdt_args10(x, args...) ___bpf_usdt_args9(args), ({ long _x; bpf_usdt_arg(ctx, 9, &_x); _x; })
|
||||
#define ___bpf_usdt_args11(x, args...) ___bpf_usdt_args10(args), ({ long _x; bpf_usdt_arg(ctx, 10, &_x); _x; })
|
||||
#define ___bpf_usdt_args12(x, args...) ___bpf_usdt_args11(args), ({ long _x; bpf_usdt_arg(ctx, 11, &_x); _x; })
|
||||
#define ___bpf_usdt_args(args...) ___bpf_apply(___bpf_usdt_args, ___bpf_narg(args))(args)
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user