diff options
author | Mattias Andrée <maandree@kth.se> | 2023-12-16 12:40:10 +0100 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2023-12-16 12:40:10 +0100 |
commit | 683f205402a99cfc8cea46c83ce9b46a42616d42 (patch) | |
tree | f6ee1619454a6ec8b9e31770bbbc2abf36aae2fd /linux/structs.c | |
parent | Improve portability (diff) | |
download | libsyscalls-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 '')
-rw-r--r-- | linux/structs.c | 248 |
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; +} |