summaryrefslogtreecommitdiffstats
path: root/common.h
blob: 8b2ff2b40da0e25b12dae57d7ff85ce7f9ec27c8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/* 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__\
	}