diff --git a/README b/README new file mode 100644 index 0000000..90643d0 --- /dev/null +++ b/README @@ -0,0 +1,21 @@ + +This is a mirror of bpf-next linux tree +(https://kernel.googlesource.com/pub/scm/linux/kernel/git/bpf/bpf-next) +bpf-next/tools/lib/bpf directory plus its supporting header files. + +The following files will by sync'ed with bpf-next repo: + src/ <-> bpf-next/tools/lib/bpf/ + include/uapi/linux/{bpf.h,btf.h} <-> bpf-next/tools/include/uapi/linux/{bpf.h,btf.h} + include/tools/libc_compat.h <-> bpf-next/tools/include/tools/libc_compat.h + +Other header files at this repo (include/linux/*.h) are reduced versions of +their counterpart files at bpf-next/tools/include/linux/*.h to make compilation +successful. + +Build +===== + +To build, + cd src + make +and it will build libbpf.a library diff --git a/include/linux/err.h b/include/linux/err.h index 1bafb5a..9289c24 100644 --- a/include/linux/err.h +++ b/include/linux/err.h @@ -3,9 +3,30 @@ #ifndef __LINUX_ERR_H #define __LINUX_ERR_H +#include + +#define MAX_ERRNO 4095 + +#define IS_ERR_VALUE(x) ((x) >= (unsigned long)-MAX_ERRNO) + static inline void * ERR_PTR(long error_) { - return (void *) error_; + return (void *) error_; +} + +static inline long PTR_ERR(const void *ptr) +{ + return (long) ptr; +} + +static inline bool IS_ERR(const void *ptr) +{ + return IS_ERR_VALUE((unsigned long)ptr); +} + +static inline bool IS_ERR_OR_NULL(const void *ptr) +{ + return (!ptr) || IS_ERR_VALUE((unsigned long)ptr); } #endif diff --git a/include/linux/kernel.h b/include/linux/kernel.h index bf88cff..cf897a6 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -3,10 +3,41 @@ #ifndef __LINUX_KERNEL_H #define __LINUX_KERNEL_H +#ifndef offsetof #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif -#define container_of(ptr, type, member) ({ \ - const typeof(((type *)0)->member) * __mptr = (ptr); \ - (type *)((char *)__mptr - offsetof(type, member)); }) +#ifndef container_of +#define container_of(ptr, type, member) ({ \ + const typeof(((type *)0)->member) * __mptr = (ptr); \ + (type *)((char *)__mptr - offsetof(type, member)); }) +#endif + +#ifndef max +#define max(x, y) ({ \ + typeof(x) _max1 = (x); \ + typeof(y) _max2 = (y); \ + (void) (&_max1 == &_max2); \ + _max1 > _max2 ? _max1 : _max2; }) +#endif + +#ifndef min +#define min(x, y) ({ \ + typeof(x) _min1 = (x); \ + typeof(y) _min2 = (y); \ + (void) (&_min1 == &_min2); \ + _min1 < _min2 ? _min1 : _min2; }) +#endif + +#ifndef roundup +#define roundup(x, y) ( \ +{ \ + const typeof(y) __y = y; \ + (((x) + (__y - 1)) / __y) * __y; \ +} \ +) +#endif + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif diff --git a/include/linux/list.h b/include/linux/list.h index 2d5703e..e3814f7 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -7,6 +7,71 @@ #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) +#define POISON_POINTER_DELTA 0 +#define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA) +#define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA) + + +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void __list_del_entry(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + #define list_entry(ptr, type, member) \ container_of(ptr, type, member) #define list_first_entry(ptr, type, member) \ diff --git a/include/linux/overflow.h b/include/linux/overflow.h index c84dc34..53d7580 100644 --- a/include/linux/overflow.h +++ b/include/linux/overflow.h @@ -3,11 +3,15 @@ #ifndef __LINUX_OVERFLOW_H #define __LINUX_OVERFLOW_H -#define is_signed_type(type) (((type)(-1)) < (type)1) +#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)) +#ifndef unlikely +#define unlikely(x) __builtin_expect(!!(x), 0) +#endif + #ifdef __GNUC__ #define GCC_VERSION (__GNUC__ * 10000 \ + __GNUC_MINOR__ * 100 \ @@ -30,26 +34,6 @@ #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. */ @@ -65,49 +49,6 @@ __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 @@ -132,23 +73,12 @@ typeof(a) __tmin = type_min(typeof(a)); \ (void) (&__a == &__b); \ (void) (&__a == __d); \ - *__d = (u64)__a * (u64)__b; \ + *__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), \ @@ -157,61 +87,4 @@ #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 diff --git a/include/linux/types.h b/include/linux/types.h index 3ddd19b..bae1ed8 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -7,22 +7,9 @@ #include #include -#define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */ #include #include -typedef uint64_t u64; -typedef int64_t s64; - -typedef __u32 u32; -typedef __s32 s32; - -typedef __u16 u16; -typedef __s16 s16; - -typedef __u8 u8; -typedef __s8 s8; - #define __bitwise__ #define __bitwise __bitwise__ diff --git a/scripts/check-reallocarray.sh b/scripts/check-reallocarray.sh new file mode 100755 index 0000000..aced5a1 --- /dev/null +++ b/scripts/check-reallocarray.sh @@ -0,0 +1,18 @@ +#/bin/sh + +tfile=$(mktemp /tmp/test_reallocarray_XXXXXXXX.c) +ofile=${tfile%.c}.o + +cat > $tfile < + +int main(void) +{ + return !!reallocarray(NULL, 1, 1); +} +EOL + +gcc $tfile -o $ofile >& /dev/null +if [ $? -ne 0 ]; then echo "FAIL"; fi +/bin/rm -f $tfile $ofile diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..9d4fa44 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) + +TOPDIR = .. +INCLUDES = -I. -I$(TOPDIR)/include -I$(TOPDIR)/include/uapi +CFLAGS = $(INCLUDES) -O2 -Werror -Wall + +FEATURE_REALLOCARRAY := $(shell $(TOPDIR)/scripts/check-reallocarray.sh) +ifneq ($(FEATURE_REALLOCARRAY),) + CFLAGS += -DCOMPAT_NEED_REALLOCARRAY +endif + +OBJFILES = bpf.o btf.o libbpf.o libbpf_errno.o netlink.o nlattr.o str_error.o + +all: libbpf.a + +libbpf.a: $(OBJFILES) + /bin/rm -f $@; /bin/ar rcs $@ $^ + +%.o: %.c + gcc $(CFLAGS) -c $< -o $@ + +clean: + /bin/rm -f libbpf.a $(OBJFILES)