summaryrefslogtreecommitdiffstats
path: root/linux/structs.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2023-12-16 12:40:10 +0100
committerMattias Andrée <maandree@kth.se>2023-12-16 12:40:10 +0100
commit683f205402a99cfc8cea46c83ce9b46a42616d42 (patch)
treef6ee1619454a6ec8b9e31770bbbc2abf36aae2fd /linux/structs.c
parentImprove portability (diff)
downloadlibsyscalls-683f205402a99cfc8cea46c83ce9b46a42616d42.tar.gz
libsyscalls-683f205402a99cfc8cea46c83ce9b46a42616d42.tar.bz2
libsyscalls-683f205402a99cfc8cea46c83ce9b46a42616d42.tar.xz
All kinds of stuff
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'linux/structs.c')
-rw-r--r--linux/structs.c248
1 files changed, 248 insertions, 0 deletions
diff --git a/linux/structs.c b/linux/structs.c
new file mode 100644
index 0000000..d9ac2d7
--- /dev/null
+++ b/linux/structs.c
@@ -0,0 +1,248 @@
+/* See LICENSE file for copyright and license details. */
+
+/* This file is included from ../libsyscalls_get_struct_description.c */
+
+
+/* Don't forget to add new ones to ../libsyscalls.h */
+#define LIST_LINUX_STRUCTS(X, D)\
+ X(STRUCT, AIO_SIGSET, 0 /* TODO bitmask */,\
+ FIELD("sigmask", ULONG_ARRAY, IN, INPTR),\
+ FIELD("sigsetsize", SIZE, IN)) D\
+ X(STRUCT, COMPAT_AIO_SIGSET, 0 /* TODO bitmask */,\
+ FIELD("sigmask", UINT32, IN, OUT),\
+ FIELD("sigsetsize", UINT32, IN, OUT)) D\
+ X(STRUCT, CACHESTAT, 0,\
+ FIELD("nr_cache", UINT64, IN, OUT),\
+ FIELD("nr_dirty", UINT64, IN, OUT),\
+ FIELD("nr_writeback", UINT64, IN, OUT),\
+ FIELD("nr_evicted", UINT64, IN, OUT),\
+ FIELD("nr_recently_evicted", UINT64, IN, OUT)) D\
+ X(STRUCT, CACHESTAT_RANGE, 0,\
+ FIELD("off", UINT64, IN, OUT),\
+ FIELD("len", UINT64, IN, OUT)) D\
+ X(STRUCT, CLONE_ARGS, 0, /* TODO which fields are IN and OUT? */\
+ FIELD("flags", UINT64, IN) /* TODO bitmask */,\
+ FIELD("pidfd", UINT64, IN) /* TODO actually (int *) */,\
+ FIELD("child_tid", UINT64, IN) /* TODO actually (pid_t *) */,\
+ FIELD("parent_tid", UINT64, IN) /* TODO actually (pid_t *) */,\
+ FIELD("exit_signal", UINT64, IN) /* TODO actually INT_SIGNAL */,\
+ FIELD("stack", UINT64, IN),\
+ FIELD("stack_size", UINT64, IN),\
+ FIELD("tls", UINT64, IN), /* TODO actually MEMORY_ADDRESS */\
+ /* Since Linux 5.5: */\
+ FIELD("set_tid", UINT64, IN), /* TODO acually (pid_t *) with count in next field */\
+ FIELD("set_tid_size", UINT64, IN),\
+ FIELD("cgroup", UINT64, IN)) /* TODO actually INT_FD */ D\
+ X(STRUCT, EPOLL_EVENT, 0, /* TODO different in libc */\
+ FIELD("events", UINT, IN, OUT) /* TODO bitmask */,\
+ FIELD("data", UINT64, PARTIAL, IN, OUT)) D\
+ X(STRUCT, OABI_EPOLL_EVENT, 0, /* TODO different in libc */\
+ FIELD("events", UINT, IN, OUT) /* TODO bitmask */,\
+ FIELD("data", UINT64_FRONT_32, PARTIAL, IN, OUT),\
+ FIELD("data", UINT64_BACK_32, PARTIAL, IN, OUT)) D\
+ X(STRUCT, FILE_HANDLE, 0) D /* TODO */\
+ X(STRUCT, FUTEX_WAITV, 0,\
+ FIELD("val", UINT64, IN, OUT),\
+ FIELD("uaddr", UINT64, IN, OUT), /* TODO actually (void *) */\
+ FIELD("flags", UINT32, IN, OUT), /* TODO bitmask */\
+ FIELD(NULL, UINT32, IN, OUT)) D\
+ X(STRUCT, IOB, 0) D /* TODO */\
+ X(STRUCT, IOVEC, 0) D /* TODO */\
+ X(STRUCT, IO_EVENT, 0,\
+ FIELD("data", UINT64, IN, OUT),\
+ FIELD("obj", UINT64, IN, OUT),\
+ FIELD("res", INT64, IN, OUT),\
+ FIELD("res2", INT64, IN, OUT)) D\
+ X(STRUCT, IO_URING_PARAMS, 0) D /* TODO */\
+ X(STRUCT, ITIMERSPEC, 0,\
+ FIELD("it_interval", STRUCT_TIMESPEC, IN, OUT),\
+ FIELD("it_value", STRUCT_TIMESPEC, IN, OUT)) D\
+ X(STRUCT, ITIMERSPEC64, 0,\
+ FIELD("it_interval", STRUCT_TIMESPEC64, IN, OUT),\
+ FIELD("it_value", STRUCT_TIMESPEC64, IN, OUT)) D\
+ X(STRUCT, KEXEC_SEGMENT, 0) D /* TODO */\
+ X(STRUCT, COMPAT_KEXEC_SEGMENT, 0) D /* TODO */\
+ X(STRUCT, LANDLOCK_RULESET_ATTR, 0) D /* TODO */\
+ X(STRUCT, LINUX_DIRENT, 0) D /* TODO */\
+ X(STRUCT, LINUX_DIRENT64, 0) D /* TODO */\
+ X(STRUCT, MMAP_ARG_STRUCT, 0) D /* TODO */\
+ X(STRUCT, MMSGHDR, 0) D /* TODO */\
+ X(STRUCT, MOUNT_ATTR, 0) D /* TODO */\
+ X(STRUCT, MQ_ATTR, 0) D /* TODO */\
+ X(STRUCT, MSGBUF, 0) D /* TODO */\
+ X(STRUCT, MSGHDR, 0) D /* TODO */\
+ X(STRUCT, MSQID_DS, 0) D /* TODO */\
+ X(STRUCT, NEW_UTSNAME, 0,\
+ FIELD("sysname", BUFFER_65, OUT),\
+ FIELD("nodename", BUFFER_65, OUT),\
+ FIELD("release", BUFFER_65, OUT),\
+ FIELD("version", BUFFER_65, OUT),\
+ FIELD("machine", BUFFER_65, OUT),\
+ FIELD("domainname", BUFFER_65, OUT)) D\
+ X(STRUCT, OLDOLD_UTSNAME, 0,\
+ FIELD("sysname", BUFFER_9, OUT),\
+ FIELD("nodename", BUFFER_9, OUT),\
+ FIELD("release", BUFFER_9, OUT),\
+ FIELD("version", BUFFER_9, OUT),\
+ FIELD("machine", BUFFER_9, OUT)) D\
+ X(STRUCT, OLD_ITIMERSPEC32, 0,\
+ FIELD("it_interval", STRUCT_OLD_TIMESPEC32, IN, OUT),\
+ FIELD("it_value", STRUCT_OLD_TIMESPEC32, IN, OUT)) D\
+ X(STRUCT, ITIMERVAL, 0,\
+ FIELD("it_interval", STRUCT_TIMEVAL, IN, OUT),\
+ FIELD("it_value", STRUCT_TIMEVAL, IN, OUT)) D\
+ X(STRUCT, OLD_ITIMERVAL, 0,\
+ FIELD("it_interval", STRUCT_OLD_TIMEVAL, IN, OUT),\
+ FIELD("it_value", STRUCT_OLD_TIMEVAL, IN, OUT)) D\
+ X(STRUCT, OLD_LINUX_DIRENT, 0) D /* TODO */\
+ X(STRUCT, OLD_SIGACTION, 0) D /* TODO */\
+ X(STRUCT, OLD_STAT, 0) D /* TODO */\
+ X(STRUCT, OLD_TIMESPEC32, 0) D /* TODO */\
+ X(STRUCT, OLD_TIMEVAL, 0) D /* TODO */\
+ X(STRUCT, OLD_TIMEVAL32, 0) D /* TODO */\
+ X(STRUCT, OLD_TIMEX32, 0) D /* TODO */\
+ X(STRUCT, OLD_UTIMBUF32, 0) D /* TODO */\
+ X(STRUCT, OLD_UTSNAME, 0,\
+ FIELD("sysname", BUFFER_65, OUT),\
+ FIELD("nodename", BUFFER_65, OUT),\
+ FIELD("release", BUFFER_65, OUT),\
+ FIELD("version", BUFFER_65, OUT),\
+ FIELD("machine", BUFFER_65, OUT)) D\
+ X(STRUCT, OPEN_HOW, 0) D /* TODO */\
+ X(STRUCT, PERF_EVENT_ATTR, 0) D /* TODO */\
+ X(STRUCT, POLLFD, 0,\
+ FIELD("pollfd", INT_FD, IN),\
+ FIELD("events", SHORT, IN), /* TODO bitmask */\
+ FIELD("revents", SHORT, OUT)) D /* TODO bitmask */\
+ X(STRUCT, RLIMIT, 0,\
+ FIELD("rlim_cur", ULONG, IN, OUT),\
+ FIELD("rlim_max", ULONG, IN, OUT)) D\
+ X(STRUCT, RLIMIT64, 0,\
+ FIELD("rlim_cur", UINT64, IN, OUT),\
+ FIELD("rlim_max", UINT64, IN, OUT)) D\
+ X(STRUCT, COMPAT_RLIMIT, 0,\
+ FIELD("rlim_cur", UINT32, IN, OUT),\
+ FIELD("rlim_max", UINT32, IN, OUT)) D\
+ X(STRUCT, ROBUST_LIST_HEAD, 0) D /* TODO */\
+ X(STRUCT, RSEQ, 0) D /* TODO */\
+ X(STRUCT, RUSAGE, 0) D /* TODO */\
+ X(STRUCT, SCHED_ATTR, 0,\
+ FIELD("size", UINT32, IN, OUT),\
+ FIELD("sched_policy", UINT32, IN, OUT),\
+ FIELD("sched_flags", UINT64, IN, OUT),\
+ FIELD("sched_nice", INT32, IN, OUT),\
+ FIELD("sched_priority", UINT32, IN, OUT),\
+ FIELD("sched_runtime", UINT64, IN, OUT),\
+ FIELD("sched_deadline", UINT32, IN, OUT),\
+ FIELD("sched_period", UINT32, IN, OUT)) D\
+ X(STRUCT, SCHED_PARAM, 0,\
+ FIELD("sched_priority", INT, IN, OUT)) D\
+ X(STRUCT, SEL_ARG_STRUCT, 0) D /* TODO */\
+ X(STRUCT, SEMBUF, 0,\
+ FIELD("sem_num", USHORT, IN, OUT),\
+ FIELD("sem_op", SHORT, IN, OUT), /* TODO enum */\
+ FIELD("sem_flg", SHORT, IN, OUT)) D /* TODO bitmask */\
+ X(STRUCT, SEMID_DS, 0) D /* TODO */\
+ X(STRUCT, SHMID_DS, 0) D /* TODO */\
+ X(STRUCT, SIGACTION, 0) D /* TODO */\
+ X(STRUCT, SIGALTSTACK, 0) D /* TODO */\
+ X(STRUCT, SIGEVENT, 0) D /* TODO */\
+ X(STRUCT, SIGINFO, 0) D /* TODO */\
+ X(STRUCT, SOCKADDR, 0) D /* TODO */\
+ X(STRUCT, STAT, 0) D /* TODO */\
+ X(STRUCT, STAT64, 0) D /* TODO */\
+ X(STRUCT, STATFS, 0) D /* TODO */\
+ X(STRUCT, STATFS64, 0) D /* TODO */\
+ X(STRUCT, STATX, 0) D /* TODO */\
+ X(STRUCT, SYSINFO, 0) D /* TODO */\
+ X(STRUCT, TIMESPEC, 0) D /* TODO */\
+ X(STRUCT, TIMESPEC64, 0) D /* TODO */\
+ X(STRUCT, TIMEVAL, 0) D /* TODO */\
+ X(STRUCT, TIMEX, 0) D /* TODO */\
+ X(STRUCT, TIMEZONE, 0) D /* TODO */\
+ X(STRUCT, TMS, 0) D /* TODO */\
+ X(STRUCT, USTAT, 0) D /* TODO */\
+ X(STRUCT, UTIMBUF, 0) D /* TODO */\
+ X(UNION, BPF_ATTR, 0) /* TODO */
+
+
+#define X(TYPE, NAME, ...)\
+ static struct libsyscalls_structure_description linux_##TYPE##_##NAME##_prototype = TYPE(__VA_ARGS__)
+ LIST_LINUX_STRUCTS(X, ;);
+#undef X
+
+
+static enum libsyscalls_error
+fix_linux_struct_description(enum libsyscalls_arch arch, enum libsyscalls_datatype datatype, unsigned class,
+ const void *data, size_t data_size, struct libsyscalls_structure_description *description)
+{
+ switch ((int)datatype) {
+ case LIBSYSCALLS_TYPE_STRUCT_SOCKADDR:
+ if (class != LIBSYSCALLS_TYPEBITS_SCALAR)
+ return LIBSYSCALLS_E_NOSUCHTYPE;
+ description->size = 0;
+ description->relative_position_of_size = +1;
+ description->absolute_position_of_size = -1;
+ /* TODO that is the alignment of `struct sockaddr`? */
+ break;
+
+ case LIBSYSCALLS_TYPE_STRUCT_CLONE_ARGS:
+ description->alignment = 64;
+ break;
+
+ case LIBSYSCALLS_TYPE_STRUCT_RSEQ:
+ description->alignment = 4 * 64;
+ break;
+
+ default:
+ break;
+ }
+
+ (void) arch;
+ (void) data;
+ (void) data_size;
+ return LIBSYSCALLS_E_OK;
+}
+
+
+static enum libsyscalls_error
+get_linux_struct_description(enum libsyscalls_arch arch, enum libsyscalls_datatype datatype, unsigned class,
+ const void *data, size_t data_size, struct libsyscalls_structure_description **description_out,
+ int *dont_align_fields_out)
+{
+ struct libsyscalls_structure_description *description;
+
+ switch ((int)datatype) {
+ case LIBSYSCALLS_TYPE_STRUCT_EPOLL_EVENT:
+ if (arch == LIBSYSCALLS_ARCH_AMD64 || arch == LIBSYSCALLS_ARCH_AMD64_X32)
+ datatype = LIBSYSCALLS_TYPE_STRUCT_OABI_EPOLL_EVENT;
+ break;
+
+ default:
+ break;
+ }
+
+#define CASE(TYPE, NAME, ...)\
+ case LIBSYSCALLS_TYPE_##TYPE##_##NAME:\
+ description = copy_struct(&linux_##TYPE##_##NAME##_prototype);\
+ break
+
+ switch ((int)datatype) {
+ LIST_LINUX_STRUCTS(CASE, ;);
+ default:
+ return LIBSYSCALLS_E_NOSUCHTYPE;
+ }
+
+#undef CASE
+
+ if (!description)
+ return LIBSYSCALLS_E_NOMEM;
+
+ (void) class;
+ (void) data;
+ (void) data_size;
+
+ *description_out = description;
+ *dont_align_fields_out = 0;
+ return LIBSYSCALLS_E_OK;
+}