diff options
author | Mattias Andrée <maandree@kth.se> | 2023-12-03 19:23:35 +0100 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2023-12-03 19:23:35 +0100 |
commit | c131f122778c62f920a99bbf854ced4a37ee8b03 (patch) | |
tree | 14c933f98f4d64dffb0a594bc40dd5121c6c5a8e /libsyscalls_get_syscall_display_info.c | |
download | libsyscalls-c131f122778c62f920a99bbf854ced4a37ee8b03.tar.gz libsyscalls-c131f122778c62f920a99bbf854ced4a37ee8b03.tar.bz2 libsyscalls-c131f122778c62f920a99bbf854ced4a37ee8b03.tar.xz |
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
-rw-r--r-- | libsyscalls_get_syscall_display_info.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/libsyscalls_get_syscall_display_info.c b/libsyscalls_get_syscall_display_info.c new file mode 100644 index 0000000..5b39284 --- /dev/null +++ b/libsyscalls_get_syscall_display_info.c @@ -0,0 +1,148 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#include <stdalign.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +#define LOWEST_BIT(X) ((X) & ~((X) - 1)) +#define POST_HIGHEST_OF_CONSECUTIVELY_BITS(X) ((X) + LOWEST_BIT(X)) + + +static inline signed char +trailing_zeroes(unsigned long long int x) { + int r = 0; + if (x == 0) + return -1; + for (; (x & 1) == 0; x >>= 1) + r += 1; + return (signed char)r; +} + + +static int +signed_named_number_cmp(const void *a_, const void *b_) +{ + const struct libsyscalls_named_number *a = a_, *b = b_; + return a->number.s < b->number.s ? -1 : a->number.s > b->number.s; +} + + +static int +unsigned_named_number_cmp(const void *a_, const void *b_) +{ + const struct libsyscalls_named_number *a = a_, *b = b_; + return a->number.u < b->number.u ? -1 : a->number.u > b->number.u; +} + + +static const char * +extract_signal(enum libsyscalls_os os, enum libsyscalls_arch arch, + unsigned long long int *valuep, char *fallback_out, int is_signed) +{ + const struct libsyscalls_named_number *signals, *found; + size_t nsignals; + struct libsyscalls_named_number key = {.number.u = *valuep}; + + if (libsyscalls_get_signals(os, arch, &signals, &nsignals)) + return NULL; + + found = bsearch(&key, signals, nsignals, sizeof(key), + is_signed ? &signed_named_number_cmp : &unsigned_named_number_cmp); + if (!found) + return NULL; + + *valuep = 0; + return found->name; +} + + +static struct libsyscalls_syscall_display_info * +build_syscall_display_info(void *data, size_t data_size, size_t data_align, + libsyscalls_symbol_printer_function **funcs, + const struct libsyscalls_syscall_abi *syscall, int nargs, int nsyms) +{ + struct libsyscalls_syscall_display_info *ret; + size_t size, dataoff, paramoff; + int i; + + size = sizeof(*ret); + + if (size & (data_align - 1)) { + size |= data_align - 1; + size += 1; + } + dataoff = size; + size += nsyms * data_size; + + if (size & (alignof(*ret->params) - 1)) { + size |= alignof(*ret->params) - 1; + size += 1; + } + paramoff = size; + size += (nargs + 1) * sizeof(*ret->params); + + ret = calloc(1, size); + if (!ret) + return NULL; + + ret->size = sizeof(*ret); + ret->params = (void *)&((char *)ret)[paramoff]; + ret->retvalue = &ret->params[nargs]; + + nsyms = 0; + for (i = 0; i < nargs; i++) { + ret->params[i].type = syscall->parameters_types[i]; + if (funcs[i]) { + ret->params[i].function = funcs[i]; + ret->params[i].data = (void *)&((char *)ret)[dataoff + nsyms * data_size]; + memcpy(ret->params[i].data, &((char *)data)[i * data_size], data_size); + nsyms++; + } + } + ret->retvalue->type = syscall->return_type; + ret->retvalue->expect_zero = syscall->expect_zero; + if (funcs[i]) { + ret->retvalue->function = funcs[i]; + ret->retvalue->data = (void *)&((char *)ret)[dataoff + nsyms * data_size]; + memcpy(ret->retvalue->data, &((char *)data)[i * data_size], data_size); + } + + return ret; +} + + +#include "generated/symbols.c" + + +enum libsyscalls_error +libsyscalls_get_syscall_display_info(enum libsyscalls_os os, enum libsyscalls_arch arch, + const struct libsyscalls_syscall_abi *syscall, + long long int syscall_number, + unsigned long long int *syscall_arguments, + struct libsyscalls_syscall_display_info **info_out) +{ + struct libsyscalls_syscall_display_info *info; + + if (!syscall || !syscall_arguments || !info_out) + return LIBSYSCALLS_E_INVAL; + +#define CASE(UPPERCASE, LOWERCASE)\ + case LIBSYSCALLS_OS_##UPPERCASE:\ + info = get_##LOWERCASE##_syscall_display_info(arch, syscall, syscall_number, syscall_arguments);\ + break + + switch ((int)os) { + LIST_OSES(CASE, ;); + default: + return LIBSYSCALLS_E_OSNOSUP; + } + +#undef CASE + + if (!info) + return LIBSYSCALLS_E_NOMEM; + *info_out = info; + return LIBSYSCALLS_E_OK; +} |