// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** * @file * * Miscellanous utility functions. * * Several of these are taken from the Linux kernel source. */ #ifndef DRGN_UTIL_H #define DRGN_UTIL_H #include #include #include #include #include #include #ifndef LIBDRGN_PUBLIC #define LIBDRGN_PUBLIC __attribute__((visibility("default"))) #endif #ifdef NDEBUG #define UNREACHABLE() __builtin_unreachable() #else #define UNREACHABLE() assert(!"reachable") #endif #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) #define __compiletime_error(message) __attribute__((__error__(message))) #else #define __compiletime_error(message) #endif #ifdef __OPTIMIZE__ # define __compiletime_assert(condition, msg, prefix, suffix) \ do { \ extern void prefix ## suffix(void) __compiletime_error(msg); \ if (!(condition)) \ prefix ## suffix(); \ } while (0) #else # define __compiletime_assert(condition, msg, prefix, suffix) do { } while (0) #endif #define _compiletime_assert(condition, msg, prefix, suffix) \ __compiletime_assert(condition, msg, prefix, suffix) #define compiletime_assert(condition, msg) \ _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); })) #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) #define container_of(ptr, type, member) ({ \ void *__mptr = (void *)(ptr); \ BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ !__same_type(*(ptr), void), \ "pointer type mismatch in container_of()"); \ ((type *)(__mptr - offsetof(type, member))); }) static inline bool strstartswith(const char *s, const char *prefix) { return strncmp(s, prefix, strlen(prefix)) == 0; } static inline void *malloc_array(size_t nmemb, size_t size) { size_t bytes; if (__builtin_mul_overflow(nmemb, size, &bytes)) { errno = ENOMEM; return NULL; } return malloc(bytes); } static inline void *malloc64(uint64_t size) { if (size > SIZE_MAX) return NULL; return malloc(size); } #endif /* DRGN_UTIL_H */