From c131f122778c62f920a99bbf854ced4a37ee8b03 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sun, 3 Dec 2023 19:23:35 +0100 Subject: First commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- libsyscalls_get_syscall_display_info.c | 148 +++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 libsyscalls_get_syscall_display_info.c (limited to 'libsyscalls_get_syscall_display_info.c') 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 +#include +#include +#include + + +#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; +} -- cgit v1.2.3-70-g09d2