/* 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; }