summaryrefslogtreecommitdiffstats
path: root/libsyscalls_get_syscall_display_info.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2023-12-03 19:23:35 +0100
committerMattias Andrée <maandree@kth.se>2023-12-03 19:23:35 +0100
commitc131f122778c62f920a99bbf854ced4a37ee8b03 (patch)
tree14c933f98f4d64dffb0a594bc40dd5121c6c5a8e /libsyscalls_get_syscall_display_info.c
downloadlibsyscalls-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 'libsyscalls_get_syscall_display_info.c')
-rw-r--r--libsyscalls_get_syscall_display_info.c148
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;
+}