mirror of
https://github.com/netdata/libbpf.git
synced 2026-03-22 09:19:06 +08:00
This initial commit added the following files
from bpf-next repository:
src:
<files from linux:tools/lib/bpf>
bpf.c bpf.h btf.c btf.h libbpf.c libbpf.h
libbpf_errno.c netlink.c nlattr.c nlattr.h
str_error.c str_error.h
include:
<files from linux:tools/include/uapi/linux>
uapi/linux/{bpf.h, btf.h}
<files from linux:tools/include/tools>
tools/libc_compat.h
The following files are also added:
include/linux/{err.h, kernel.h, list.h, overflow.h, types.h}
These files are customized headers to satisfy compilation.
Their original counterparts are at linux:tools/include/linux
directory.
Signed-off-by: Yonghong Song <yhs@fb.com>
218 lines
6.0 KiB
C
218 lines
6.0 KiB
C
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
|
|
|
#ifndef __LINUX_OVERFLOW_H
|
|
#define __LINUX_OVERFLOW_H
|
|
|
|
#define is_signed_type(type) (((type)(-1)) < (type)1)
|
|
#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
|
|
#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
|
|
#define type_min(T) ((T)((T)-type_max(T)-(T)1))
|
|
|
|
#ifdef __GNUC__
|
|
#define GCC_VERSION (__GNUC__ * 10000 \
|
|
+ __GNUC_MINOR__ * 100 \
|
|
+ __GNUC_PATCHLEVEL__)
|
|
#if GCC_VERSION >= 50100
|
|
#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
|
|
|
|
#define check_mul_overflow(a, b, d) ({ \
|
|
typeof(a) __a = (a); \
|
|
typeof(b) __b = (b); \
|
|
typeof(d) __d = (d); \
|
|
(void) (&__a == &__b); \
|
|
(void) (&__a == __d); \
|
|
__builtin_mul_overflow(__a, __b, __d); \
|
|
})
|
|
|
|
#else
|
|
|
|
|
|
/* Checking for unsigned overflow is relatively easy without causing UB. */
|
|
#define __unsigned_add_overflow(a, b, d) ({ \
|
|
typeof(a) __a = (a); \
|
|
typeof(b) __b = (b); \
|
|
typeof(d) __d = (d); \
|
|
(void) (&__a == &__b); \
|
|
(void) (&__a == __d); \
|
|
*__d = __a + __b; \
|
|
*__d < __a; \
|
|
})
|
|
#define __unsigned_sub_overflow(a, b, d) ({ \
|
|
typeof(a) __a = (a); \
|
|
typeof(b) __b = (b); \
|
|
typeof(d) __d = (d); \
|
|
(void) (&__a == &__b); \
|
|
(void) (&__a == __d); \
|
|
*__d = __a - __b; \
|
|
__a < __b; \
|
|
})
|
|
/*
|
|
* If one of a or b is a compile-time constant, this avoids a division.
|
|
*/
|
|
#define __unsigned_mul_overflow(a, b, d) ({ \
|
|
typeof(a) __a = (a); \
|
|
typeof(b) __b = (b); \
|
|
typeof(d) __d = (d); \
|
|
(void) (&__a == &__b); \
|
|
(void) (&__a == __d); \
|
|
*__d = __a * __b; \
|
|
__builtin_constant_p(__b) ? \
|
|
__b > 0 && __a > type_max(typeof(__a)) / __b : \
|
|
__a > 0 && __b > type_max(typeof(__b)) / __a; \
|
|
})
|
|
|
|
/*
|
|
* For signed types, detecting overflow is much harder, especially if
|
|
* we want to avoid UB. But the interface of these macros is such that
|
|
* we must provide a result in *d, and in fact we must produce the
|
|
* result promised by gcc's builtins, which is simply the possibly
|
|
* wrapped-around value. Fortunately, we can just formally do the
|
|
* operations in the widest relevant unsigned type (u64) and then
|
|
* truncate the result - gcc is smart enough to generate the same code
|
|
* with and without the (u64) casts.
|
|
*/
|
|
|
|
/*
|
|
* Adding two signed integers can overflow only if they have the same
|
|
* sign, and overflow has happened iff the result has the opposite
|
|
* sign.
|
|
*/
|
|
#define __signed_add_overflow(a, b, d) ({ \
|
|
typeof(a) __a = (a); \
|
|
typeof(b) __b = (b); \
|
|
typeof(d) __d = (d); \
|
|
(void) (&__a == &__b); \
|
|
(void) (&__a == __d); \
|
|
*__d = (u64)__a + (u64)__b; \
|
|
(((~(__a ^ __b)) & (*__d ^ __a)) \
|
|
& type_min(typeof(__a))) != 0; \
|
|
})
|
|
|
|
/*
|
|
* Subtraction is similar, except that overflow can now happen only
|
|
* when the signs are opposite. In this case, overflow has happened if
|
|
* the result has the opposite sign of a.
|
|
*/
|
|
#define __signed_sub_overflow(a, b, d) ({ \
|
|
typeof(a) __a = (a); \
|
|
typeof(b) __b = (b); \
|
|
typeof(d) __d = (d); \
|
|
(void) (&__a == &__b); \
|
|
(void) (&__a == __d); \
|
|
*__d = (u64)__a - (u64)__b; \
|
|
((((__a ^ __b)) & (*__d ^ __a)) \
|
|
& type_min(typeof(__a))) != 0; \
|
|
})
|
|
|
|
/*
|
|
* Signed multiplication is rather hard. gcc always follows C99, so
|
|
* division is truncated towards 0. This means that we can write the
|
|
* overflow check like this:
|
|
*
|
|
* (a > 0 && (b > MAX/a || b < MIN/a)) ||
|
|
* (a < -1 && (b > MIN/a || b < MAX/a) ||
|
|
* (a == -1 && b == MIN)
|
|
*
|
|
* The redundant casts of -1 are to silence an annoying -Wtype-limits
|
|
* (included in -Wextra) warning: When the type is u8 or u16, the
|
|
* __b_c_e in check_mul_overflow obviously selects
|
|
* __unsigned_mul_overflow, but unfortunately gcc still parses this
|
|
* code and warns about the limited range of __b.
|
|
*/
|
|
|
|
#define __signed_mul_overflow(a, b, d) ({ \
|
|
typeof(a) __a = (a); \
|
|
typeof(b) __b = (b); \
|
|
typeof(d) __d = (d); \
|
|
typeof(a) __tmax = type_max(typeof(a)); \
|
|
typeof(a) __tmin = type_min(typeof(a)); \
|
|
(void) (&__a == &__b); \
|
|
(void) (&__a == __d); \
|
|
*__d = (u64)__a * (u64)__b; \
|
|
(__b > 0 && (__a > __tmax/__b || __a < __tmin/__b)) || \
|
|
(__b < (typeof(__b))-1 && (__a > __tmin/__b || __a < __tmax/__b)) || \
|
|
(__b == (typeof(__b))-1 && __a == __tmin); \
|
|
})
|
|
|
|
|
|
#define check_add_overflow(a, b, d) \
|
|
__builtin_choose_expr(is_signed_type(typeof(a)), \
|
|
__signed_add_overflow(a, b, d), \
|
|
__unsigned_add_overflow(a, b, d))
|
|
|
|
#define check_sub_overflow(a, b, d) \
|
|
__builtin_choose_expr(is_signed_type(typeof(a)), \
|
|
__signed_sub_overflow(a, b, d), \
|
|
__unsigned_sub_overflow(a, b, d))
|
|
|
|
#define check_mul_overflow(a, b, d) \
|
|
__builtin_choose_expr(is_signed_type(typeof(a)), \
|
|
__signed_mul_overflow(a, b, d), \
|
|
__unsigned_mul_overflow(a, b, d))
|
|
|
|
|
|
#endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */
|
|
|
|
/**
|
|
* array_size() - Calculate size of 2-dimensional array.
|
|
*
|
|
* @a: dimension one
|
|
* @b: dimension two
|
|
*
|
|
* Calculates size of 2-dimensional array: @a * @b.
|
|
*
|
|
* Returns: number of bytes needed to represent the array or SIZE_MAX on
|
|
* overflow.
|
|
*/
|
|
static inline size_t array_size(size_t a, size_t b)
|
|
{
|
|
size_t bytes;
|
|
|
|
if (check_mul_overflow(a, b, &bytes))
|
|
return SIZE_MAX;
|
|
|
|
return bytes;
|
|
}
|
|
|
|
/**
|
|
* array3_size() - Calculate size of 3-dimensional array.
|
|
*
|
|
* @a: dimension one
|
|
* @b: dimension two
|
|
* @c: dimension three
|
|
*
|
|
* Calculates size of 3-dimensional array: @a * @b * @c.
|
|
*
|
|
* Returns: number of bytes needed to represent the array or SIZE_MAX on
|
|
* overflow.
|
|
*/
|
|
static inline size_t array3_size(size_t a, size_t b, size_t c)
|
|
{
|
|
size_t bytes;
|
|
|
|
if (check_mul_overflow(a, b, &bytes))
|
|
return SIZE_MAX;
|
|
if (check_mul_overflow(bytes, c, &bytes))
|
|
return SIZE_MAX;
|
|
|
|
return bytes;
|
|
}
|
|
|
|
static inline size_t __ab_c_size(size_t n, size_t size, size_t c)
|
|
{
|
|
size_t bytes;
|
|
|
|
if (check_mul_overflow(n, size, &bytes))
|
|
return SIZE_MAX;
|
|
if (check_add_overflow(bytes, c, &bytes))
|
|
return SIZE_MAX;
|
|
|
|
return bytes;
|
|
}
|
|
|
|
#endif
|