diff options
| author | Andrii Nakryiko <andrii@kernel.org> | 2025-10-01 10:13:22 -0700 | 
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2025-10-01 15:27:24 -0700 | 
| commit | 44d42bd80804d117fd83b849820e26dafd25a5f9 (patch) | |
| tree | 34c36b940ced8f9a97d3b40e1a6eb2abfdbb5045 /tools/lib/bpf/libbpf_utils.c | |
| parent | a1aca22d264cdca5b20934a2413951ea7d73c594 (diff) | |
libbpf: make libbpf_errno.c into more generic libbpf_utils.c
Libbpf is missing one convenient place to put common "utils"-like code
that is generic and usable from multiple places. Use libbpf_errno.c as
the base for more generic libbpf_utils.c.
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20251001171326.3883055-2-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Diffstat (limited to 'tools/lib/bpf/libbpf_utils.c')
| -rw-r--r-- | tools/lib/bpf/libbpf_utils.c | 75 | 
1 files changed, 75 insertions, 0 deletions
| diff --git a/tools/lib/bpf/libbpf_utils.c b/tools/lib/bpf/libbpf_utils.c new file mode 100644 index 000000000000..6b180172ec6b --- /dev/null +++ b/tools/lib/bpf/libbpf_utils.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) + +/* + * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> + * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> + * Copyright (C) 2015 Huawei Inc. + * Copyright (C) 2017 Nicira, Inc. + */ + +#undef _GNU_SOURCE +#include <stdio.h> +#include <string.h> + +#include "libbpf.h" +#include "libbpf_internal.h" + +/* make sure libbpf doesn't use kernel-only integer typedefs */ +#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 + +#define ERRNO_OFFSET(e)		((e) - __LIBBPF_ERRNO__START) +#define ERRCODE_OFFSET(c)	ERRNO_OFFSET(LIBBPF_ERRNO__##c) +#define NR_ERRNO	(__LIBBPF_ERRNO__END - __LIBBPF_ERRNO__START) + +static const char *libbpf_strerror_table[NR_ERRNO] = { +	[ERRCODE_OFFSET(LIBELF)]	= "Something wrong in libelf", +	[ERRCODE_OFFSET(FORMAT)]	= "BPF object format invalid", +	[ERRCODE_OFFSET(KVERSION)]	= "'version' section incorrect or lost", +	[ERRCODE_OFFSET(ENDIAN)]	= "Endian mismatch", +	[ERRCODE_OFFSET(INTERNAL)]	= "Internal error in libbpf", +	[ERRCODE_OFFSET(RELOC)]		= "Relocation failed", +	[ERRCODE_OFFSET(VERIFY)]	= "Kernel verifier blocks program loading", +	[ERRCODE_OFFSET(PROG2BIG)]	= "Program too big", +	[ERRCODE_OFFSET(KVER)]		= "Incorrect kernel version", +	[ERRCODE_OFFSET(PROGTYPE)]	= "Kernel doesn't support this program type", +	[ERRCODE_OFFSET(WRNGPID)]	= "Wrong pid in netlink message", +	[ERRCODE_OFFSET(INVSEQ)]	= "Invalid netlink sequence", +	[ERRCODE_OFFSET(NLPARSE)]	= "Incorrect netlink message parsing", +}; + +int libbpf_strerror(int err, char *buf, size_t size) +{ +	int ret; + +	if (!buf || !size) +		return libbpf_err(-EINVAL); + +	err = err > 0 ? err : -err; + +	if (err < __LIBBPF_ERRNO__START) { +		ret = strerror_r(err, buf, size); +		buf[size - 1] = '\0'; +		return libbpf_err_errno(ret); +	} + +	if (err < __LIBBPF_ERRNO__END) { +		const char *msg; + +		msg = libbpf_strerror_table[ERRNO_OFFSET(err)]; +		ret = snprintf(buf, size, "%s", msg); +		buf[size - 1] = '\0'; +		/* The length of the buf and msg is positive. +		 * A negative number may be returned only when the +		 * size exceeds INT_MAX. Not likely to appear. +		 */ +		if (ret >= size) +			return libbpf_err(-ERANGE); +		return 0; +	} + +	ret = snprintf(buf, size, "Unknown libbpf error %d", err); +	buf[size - 1] = '\0'; +	if (ret >= size) +		return libbpf_err(-ERANGE); +	return libbpf_err(-ENOENT); +} | 
