summaryrefslogblamecommitdiffstats
path: root/common.h
blob: 8b2ff2b40da0e25b12dae57d7ff85ce7f9ec27c8 (plain) (tree)
1
2
3
4
5
6
7
8

                                                         
                       
                                          



                                                                     




                                                                                                                                                              











                                                                                                                                                              

                        
                     

                   

















                                                                                                                                  
 





                                                

 

               


                                                                                                        
                                                  

                                         



                                                                     







                                        




              





                                                                                                        
          



                                                                                                        
           



































                                                                                                        
 




















                                                                                                          



                                                                   

                                                                             

                                                                                     























                                                                                                            
/* See LICENSE file for copyright and license details. */
#ifdef REQUIRE_FLEXABLE_OR_NPARAMS
# if defined(__clang__)
#  define LIBSYSCALLS_FLEXABLE_OR_NPARAMS_
#  pragma clang diagnostic ignored "-Wgnu-flexible-array-initializer"
# elif defined(__GNUC__)
#  define LIBSYSCALLS_FLEXABLE_OR_NPARAMS_
#  pragma GCC diagnostic ignored "-Wpedantic"
# else
#  define LIBSYSCALLS_FLEXABLE_OR_NPARAMS_ NPARAMS
#  warning Setting LIBSYSCALLS_FLEXABLE_OR_NPARAMS_ to NPARAMS as it is not known that the compiler supports static allocation of structs with flexible arrays
# endif
#endif
#ifdef REQUIRE_FLEXABLE_OR_NFIELDS
# if defined(__clang__)
#  define LIBSYSCALLS_FLEXABLE_OR_NFIELDS_
#  pragma clang diagnostic ignored "-Wgnu-flexible-array-initializer"
# elif defined(__GNUC__)
#  define LIBSYSCALLS_FLEXABLE_OR_NFIELDS_
#  pragma GCC diagnostic ignored "-Wpedantic"
# else
#  define LIBSYSCALLS_FLEXABLE_OR_NFIELDS_ NFIELDS
#  warning Setting LIBSYSCALLS_FLEXABLE_OR_NFIELDS_ to NFIELDS as it is not known that the compiler supports static allocation of structs with flexible arrays
# endif
#endif
#include "libsyscalls.h"

#include <stdalign.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#if defined(__clang__)
/* We expect the user to use -Weverything */
# pragma clang diagnostic ignored "-Wimplicit-fallthrough" /* we use GCC's fall though comments */
# pragma clang diagnostic ignored "-Wcovered-switch-default" /* the user may input something invalid due to version differences */
# pragma clang diagnostic ignored "-Wc++98-compat" /* don't care about C++, especially not for internal code */
# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" /* TODO how does that make sense in C23? */
# pragma clang diagnostic ignored "-Wunsafe-buffer-usage" /* clang doesn't know what it is doing */
# pragma clang diagnostic ignored "-Wvla" /* we prefer VLA over alloca (easier to support), and we are careful */
#elif defined(__GNUC__)
/* We expect the user to use -Wall -Wextra mand maybe some other flags */
# pragma GCC diagnostic ignored "-Wnonnull-compare" /* why should I trust that the user is using the same compiler? */
# pragma GCC diagnostic ignored "-Winline" /* it's just a preference, up to the compiler to decide */
#endif


#if defined(__GNUC__)
# define PURE_FUNCTION __attribute__((__pure__))
#else
# define PURE_FUNCTION
#endif


#define COMMA ,

#define MISALIGNMENT(ADDR, ALIGN) ((ADDR) & ((uintptr_t)(ALIGN) - 1U))
#define ALIGNMENT_ADJUSTMENT(ADDR, ALIGN) MISALIGNMENT((ALIGN) - MISALIGNMENT((ADDR), (ALIGN)), (ALIGN))
#define ALIGN_BUF(BUF, ALIGN) (&(BUF)[(size_t)ALIGNMENT_ADJUSTMENT((uintptr_t)(char *)(BUF), (ALIGN))])
#define ELEMSOF(ARR) (sizeof(ARR) / sizeof *(ARR))
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define LOWEST_BIT(X) ((X) & ~((X) - 1))
#define POST_HIGHEST_OF_CONSECUTIVELY_BITS(X) ((X) + LOWEST_BIT((X)))
#define IS_NOT_2POW(X) ((X) & ((X) - 1))
#define SET_MASK_TRAIL(X) ((X) | ((X) - 1U))
#define USAT_MINUS(A, B) ((A) < (B) ? 0 : (A) - (B))


struct libsyscalls_symbol_printer_data {
	enum libsyscalls_arch arch;
	int nr;
	char buf[];
};

enum endian {
	Big,
	Little
};

                              /*             [------ size ------]  [align]                 */
#define LIST_ARCH_SPECS(X, D) /*             byte  intptr  size_t  intmax  endian    sign  */\
	X(LIBSYSCALLS_ARCH_ALPHA_LE,         8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_ALPHA_BE,         8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_AMD64,            8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_AMD64_X32,        8,    32,     32,     64,     Little,   TWOS_COMPLEMENT) D\
	/*
	X(LIBSYSCALLS_ARCH_ARM_OABI_LE,      8,    TODO,   TODO,   32,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_ARM_OABI_BE,      8,    TODO,   TODO,   32,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_ARM_EABI_LE,      8,    TODO,   TODO,   64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_ARM_EABI_BE,      8,    TODO,   TODO,   64,     Big,      TWOS_COMPLEMENT) D\
	*/\
	X(LIBSYSCALLS_ARCH_IA64_LE,          8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_IA64_BE,          8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_IA64_P32_LE,      8,    32,     32,     64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_IA64_P32_BE,      8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_M68K,             8,    32,     32,     16,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_MICROBLAZE_32_LE, 8,    32,     32,     32,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_MICROBLAZE_32_BE, 8,    32,     32,     32,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_MICROBLAZE_64_LE, 8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_MICROBLAZE_64_BE, 8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_MIPS_O32_LE,      8,    32,     32,     64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_MIPS_O32_BE,      8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_MIPS_N32_LE,      8,    32,     32,     64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_MIPS_N32_BE,      8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_MIPS_N64_LE,      8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_MIPS_N64_BE,      8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_PARISC_32,        8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_PARISC_64,        8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_POWERPC_32_LE,    8,    32,     32,     64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_POWERPC_32_BE,    8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_POWERPC_64_LE,    8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_POWERPC_64_BE,    8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_POWERPC_NOSPU_LE, 8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_POWERPC_NOSPU_BE, 8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_POWERPC_SPU_LE,   8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_POWERPC_SPU_BE,   8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_S390_32,          8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_S390_64,          8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_SH_LE,            8,    32,     32,     32,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_SH_BE,            8,    32,     32,     32,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_SPARC_32,         8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_SPARC_64_LE,      8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_SPARC_64_BE,      8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_I386,             8,    32,     32,     32,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_XTENSA_LE,        8,    32,     32,     64,     Little,   TWOS_COMPLEMENT) D\
	X(LIBSYSCALLS_ARCH_XTENSA_BE,        8,    32,     32,     64,     Big,      TWOS_COMPLEMENT)
	/* Don't forget to update SUPPORTED_ARCHES in Makefile */


#include "generated/oses.h"
#include "generated/arches.h"
#include "generated/lowercase.h"
#include "generated/macros.h"


#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
#endif
extern const struct libsyscalls_syscall *const *const *const libsyscalls_syscalls_tables_[];
#define X(UPPERCASE, LOWERCASE)\
	extern const struct libsyscalls_syscall *const *const libsyscalls_##LOWERCASE##_syscalls_table_[];
LIST_OSES(X,)
#undef X
#if defined(__clang__)
# pragma clang diagnostic pop
#endif


#define COUNT_LIST_(...) 1
#define COUNT_LIST(LIST_MACRO) (LIST_MACRO(COUNT_LIST_,, +,))

#define COUNT_ARGS(...) (0 __VA_OPT__(+ COUNT_ARGS_1(__VA_ARGS__)))
#define COUNT_ARG_PAIRS(...) (0 __VA_OPT__(+ COUNT_ARG_PAIRS_1(__VA_ARGS__)))

/* mk/generate.mk reads these three lines, do not format them as multiline macros! */
#define COUNT_ARGS_1(x, ...) 1 __VA_OPT__(+ COUNT_ARGS_2(__VA_ARGS__))
#define COUNT_ARG_PAIRS_1(x1, x2, ...) 1 __VA_OPT__(+ COUNT_ARG_PAIRS_2(__VA_ARGS__))
#define PARAMS_BUILD_TYPES_1(x, A, ...) LIBSYSCALLS_TYPE_##A __VA_OPT__(, PARAMS_BUILD_TYPES_2(__VA_ARGS__))

#define PARAMS(...)\
	.max_argument_count = COUNT_ARG_PAIRS(__VA_ARGS__),\
	.in_pointer_mask = PARAMS_BUILD_MASK(IN, __VA_ARGS__),\
	.out_pointer_mask = PARAMS_BUILD_MASK(OUT, __VA_ARGS__), \
	.symbolic_mask = PARAMS_BUILD_MASK(SYM, __VA_ARGS__)\
	__VA_OPT__(, .parameters_types = {PARAMS_BUILD_TYPES_1(__VA_ARGS__)})

#define ZERO(TYPE) TYPE, .expect_zero = 1
#define LIBSYSCALLS_TYPE_ZERO(TYPE) ZERO(LIBSYSCALLS_TYPE_##TYPE)

#define SYMB(TYPE) TYPE, .symbolic_return = 1
#define LIBSYSCALLS_TYPE_SYMB(TYPE) SYMB(LIBSYSCALLS_TYPE_##TYPE)

#define SYSCALL_ABI(OS, NAME, CATEGORY, SUBCATEGORY, MIN_ARGS, RETURN_TYPE, ...)\
	static struct libsyscalls_syscall_abi OS##_syscall_##NAME = {\
		.category = LIBSYSCALLS_CAT_##CATEGORY,\
		.subcategory.LOWERCASE_##CATEGORY = LIBSYSCALLS_##CATEGORY##_SUBCAT_##SUBCATEGORY,\
		.min_argument_count = MIN_ARGS,\
		.return_type = LIBSYSCALLS_TYPE_##RETURN_TYPE,\
		__VA_ARGS__\
	}