summaryrefslogtreecommitdiffstats
path: root/linux/symbols.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/symbols.c')
-rw-r--r--linux/symbols.c321
1 files changed, 321 insertions, 0 deletions
diff --git a/linux/symbols.c b/linux/symbols.c
new file mode 100644
index 0000000..d91880f
--- /dev/null
+++ b/linux/symbols.c
@@ -0,0 +1,321 @@
+/* See LICENSE file for copyright and license details. */
+
+/* This file is included from ../libsyscalls_get_syscall_display_info.c */
+
+/* TODO (see syscalls.h) */
+#define extract_linux_symbol_madvise extract_linux_symbol_noflags
+#define extract_linux_symbol_msync extract_linux_symbol_noflags
+#define extract_linux_symbol_mlock extract_linux_symbol_noflags
+#define extract_linux_symbol_mcl extract_linux_symbol_noflags
+#define extract_linux_symbol_epoll extract_linux_symbol_noflags
+#define extract_linux_symbol_sock_fd extract_linux_symbol_noflags
+#define extract_linux_symbol_dup3 extract_linux_symbol_noflags
+#define extract_linux_symbol_pipe extract_linux_symbol_noflags
+#define extract_linux_symbol_inotify_fd extract_linux_symbol_noflags
+#define extract_linux_symbol_fan_event_f extract_linux_symbol_noflags
+#define extract_linux_symbol_mq_open extract_linux_symbol_noflags
+#define extract_linux_symbol_swapon extract_linux_symbol_noflags
+#define extract_linux_symbol_inotify_mask extract_linux_symbol_noflags
+#define extract_linux_symbol_shmget extract_linux_symbol_noflags
+#define extract_linux_symbol_fan_class extract_linux_symbol_noflags
+#define extract_linux_symbol_fan_mark extract_linux_symbol_noflags
+#define extract_linux_symbol_fan extract_linux_symbol_noflags
+#define extract_linux_symbol_socket extract_linux_symbol_noflags
+#define extract_linux_symbol_reboot extract_linux_symbol_noflags
+
+
+static const char *
+extract_linux_symbol_signal(struct libsyscalls_symbol_printer_data *data, unsigned long long int *valuep, char *fallback_out)
+{
+ return extract_signal(LIBSYSCALLS_OS_LINUX, data->arch, valuep, fallback_out,
+ 0 /* doesn't matter, unsigned is probably faster */);
+}
+
+
+static const char *
+extract_linux_symbol_mode(struct libsyscalls_symbol_printer_data *data, unsigned long long int *valuep, char *fallback_out)
+{
+ unsigned long long int value;
+ size_t i;
+ *fallback_out = 'o';
+ *valuep ^= value = *valuep & 07777ULL;
+ i = 0;
+ data->buf[i++] = '0';
+ if (value & 07000) goto digits4;
+ if (value & 0700) goto digits3;
+ if (value & 070) goto digits2;
+ if (value & 07) goto digits1;
+ if (0) {
+ digits4:
+ data->buf[i++] = '0' | (value & 07000);
+ digits3:
+ data->buf[i++] = '0' | (value & 0700);
+ digits2:
+ data->buf[i++] = '0' | (value & 070);
+ digits1:
+ data->buf[i++] = '0' | (value & 07);
+ }
+ data->buf[i++] = ' ';
+ data->buf[i++] = '(';
+ data->buf[i++] = (value & 0400) ? 'r' : '-';
+ data->buf[i++] = (value & 0200) ? 'w' : '-';
+ if (value & 04000)
+ data->buf[i++] = (value & 0100) ? 's' : 'S';
+ else
+ data->buf[i++] = (value & 0100) ? 'x' : '-';
+ data->buf[i++] = (value & 040) ? 'r' : '-';
+ data->buf[i++] = (value & 020) ? 'w' : '-';
+ if (value & 02000)
+ data->buf[i++] = (value & 010) ? 's' : 'S';
+ else
+ data->buf[i++] = (value & 010) ? 'x' : '-';
+ data->buf[i++] = (value & 04) ? 'r' : '-';
+ data->buf[i++] = (value & 02) ? 'w' : '-';
+ if (value & 01000)
+ data->buf[i++] = (value & 01) ? 't' : 'T';
+ else
+ data->buf[i++] = (value & 01) ? 'x' : '-';
+ data->buf[i++] = ')';
+ data->buf[i] = '\0';
+ return data->buf;
+}
+
+
+static const char *
+extract_linux_symbol_umask(struct libsyscalls_symbol_printer_data *data, unsigned long long int *valuep, char *fallback_out)
+{
+ unsigned long long int value;
+ size_t i;
+ *fallback_out = 'o';
+ *valuep ^= value = *valuep & 0777ULL;
+ i = 0;
+ data->buf[i++] = '0';
+ if (value & 0700) goto digits3;
+ if (value & 070) goto digits2;
+ if (value & 07) goto digits1;
+ if (0) {
+ digits3:
+ data->buf[i++] = '0' | (value & 0700);
+ digits2:
+ data->buf[i++] = '0' | (value & 070);
+ digits1:
+ data->buf[i++] = '0' | (value & 07);
+ }
+ data->buf[i++] = ' ';
+ data->buf[i++] = '(';
+ data->buf[i++] = 'u';
+ data->buf[i++] = ':';
+ data->buf[i++] = ':';
+ data->buf[i++] = (value & 0400) ? '-' : 'r';
+ data->buf[i++] = (value & 0200) ? '-' : 'w';
+ data->buf[i++] = (value & 0100) ? '-' : 'x';
+ data->buf[i++] = ',';
+ data->buf[i++] = 'g';
+ data->buf[i++] = ':';
+ data->buf[i++] = ':';
+ data->buf[i++] = (value & 040) ? '-' : 'r';
+ data->buf[i++] = (value & 020) ? '-' : 'w';
+ data->buf[i++] = (value & 010) ? '-' : 'x';
+ data->buf[i++] = ',';
+ data->buf[i++] = 'o';
+ data->buf[i++] = ':';
+ data->buf[i++] = ':';
+ data->buf[i++] = (value & 04) ? '-' : 'r';
+ data->buf[i++] = (value & 02) ? '-' : 'w';
+ data->buf[i++] = (value & 01) ? '-' : 'x';
+ data->buf[i++] = ')';
+ data->buf[i] = '\0';
+ return data->buf;
+}
+
+
+static const char *
+extract_linux_symbol_dev(struct libsyscalls_symbol_printer_data *data, unsigned long long int *valuep, char *fallback_out)
+{
+ unsigned long long int value;
+ unsigned long long int major, major1, major2;
+ unsigned long long int minor, minor1, minor2;
+
+ *fallback_out = 'x';
+
+ major1 = 0xFFFFF00000000000ULL;
+ minor1 = 0x00000FFFFFF00000ULL;
+ major2 = 0x00000000000FFF00ULL;
+ minor2 = 0x00000000000000FFULL;
+
+ *valuep ^= value = *valuep & (major1 | minor1 | major2 | minor2);
+
+ major1 = (value & major1) / LOWEST_BIT(major1) * POST_HIGHEST_OF_CONSECUTIVELY_BITS(major2);
+ major2 = (value & major2) / LOWEST_BIT(major2);
+
+ minor1 = (value & minor1) / LOWEST_BIT(minor1) * POST_HIGHEST_OF_CONSECUTIVELY_BITS(minor2);
+ minor2 = (value & minor2) / LOWEST_BIT(minor2);
+
+ major = major1 | major2;
+ minor = minor1 | minor1;
+
+ sprintf(data->buf, "%llu (%llu:%llu)", value, major, minor);
+ return data->buf;
+}
+
+
+static const char *
+extract_linux_symbol_clockid_t(struct libsyscalls_symbol_printer_data *data, unsigned long long int *valuep, char *fallback_out)
+{
+ if (*valuep >= 0)
+ return NULL;
+ else if ((*valuep & 7) == 2)
+ sprintf(data->buf, "%lli (pid: %llu)", (long long int)*valuep, ~*valuep / 8);
+ else if ((*valuep & 7) == 3)
+ sprintf(data->buf, "%lli (fd: %llu)", (long long int)*valuep, ~*valuep / 8);
+ else if ((*valuep & 7) == 6)
+ sprintf(data->buf, "%lli (tid: %llu)", (long long int)*valuep, ~*valuep / 8);
+ else
+ sprintf(data->buf, "%lli (~%llu*8 + %u)", (long long int)*valuep, ~*valuep / 8, *valuep & 7);
+ *valuep = 0;
+ return data->buf;
+}
+
+
+#define SYMBOL_PRINTERS_ONLY
+#include "syscalls.h"
+#undef SYMBOL_PRINTERS_ONLY
+
+#include "../generated/linux-symbol-extractors.h"
+
+
+static int
+get_linux_symbol_extractor_by_sym_nr(LIBSYSCALLS_SYMBOL_PRINTER printer, libsyscalls_symbol_printer_function **function_out,
+ enum libsyscalls_arch arch, const struct libsyscalls_syscall_abi *syscall, int nr,
+ struct libsyscalls_symbol_printer_data *data_out)
+{
+ int ret;
+
+#define CASE(E, F, N)\
+ case E:\
+ *function_out = &F;\
+ ret = N;\
+ break
+
+ switch (printer) {
+ LIST_LINUX_EXTRACTORS(CASE, ;);
+
+ case LINUX_SYMBOL_PRINTER_SIGNAL:
+ *function_out = &extract_linux_symbol_signal;
+ ret = 1;
+ break;
+
+ default:
+ abort();
+ }
+
+#undef CASE
+
+ data_out->arch = arch;
+ data_out->nr = nr;
+
+ (void) syscall;
+ return ret;
+}
+
+
+static libsyscalls_symbol_printer_function *
+get_linux_symbol_extractor_by_arg_nr(enum libsyscalls_arch arch, const struct libsyscalls_syscall_abi *syscall,
+ int arg, struct libsyscalls_symbol_printer_data *data_out)
+{
+ int nr, n;
+ unsigned mask;
+ LIBSYSCALLS_SYMBOL_PRINTER first, second;
+ libsyscalls_symbol_printer_function *function;
+
+ if (!syscall->symbol_printer || arg >= NPARAMS) {
+ return NULL;
+ } else if (arg < 0) {
+ if (syscall->symbolic_return)
+ nr = 0;
+ else
+ return NULL;
+ } else if ((syscall->symbolic_mask >> arg) & 1) {
+ mask = (unsigned)syscall->symbolic_mask;
+ nr = (int)syscall->symbolic_return;
+ for (mask &= (1U << arg) - 1; mask; mask >>= 1)
+ nr += (int)mask & 1;
+ } else {
+ return NULL;
+ }
+
+ first = (syscall->symbol_printer & 0x00FF) >> 0;
+ second = (syscall->symbol_printer & 0xFF00) >> 8;
+ if (second && !first)
+ second = syscall->symbol_printer;
+
+ if (first) {
+ n = get_linux_symbol_extractor_by_sym_nr(first, &function, arch, syscall, nr, data_out);
+ if (nr < n)
+ goto have_fun;
+ nr -= n;
+ }
+
+ if (second) {
+ n = get_linux_symbol_extractor_by_sym_nr(second, &function, arch, syscall, nr, data_out);
+ if (nr < n)
+ goto have_fun;
+ }
+
+ abort();
+
+have_fun:
+ return function;
+}
+
+
+static struct libsyscalls_syscall_display_info *
+get_linux_syscall_display_info(enum libsyscalls_arch arch, const struct libsyscalls_syscall_abi *syscall,
+ long long int syscall_number, unsigned long long int *syscall_argument)
+{
+ LIBSYSCALLS_SYMBOL_PRINTER_DATA *data;
+ libsyscalls_symbol_printer_function **funcs;
+ int i, nargs, nsyms;
+ size_t data_size = offsetof(LIBSYSCALLS_SYMBOL_PRINTER_DATA, buf);
+ size_t data_align = alignof(*data);
+ size_t bufspace, bufspace1, bufspace2;
+ LIBSYSCALLS_SYMBOL_PRINTER first, second;
+
+ nargs = (int)syscall->max_argument_count;
+ nargs = nargs < 0 ? 0 : nargs;
+
+ first = (syscall->symbol_printer & 0x00FF) >> 0;
+ second = (syscall->symbol_printer & 0xFF00) >> 8;
+ if (second && !first)
+ second = syscall->symbol_printer;
+
+ bufspace1 = LINUX_REQUIRE_SYMBOL_BUFFER(first);
+ bufspace2 = LINUX_REQUIRE_SYMBOL_BUFFER(second);
+ bufspace = bufspace1 > bufspace2 ? bufspace1 : bufspace2;
+ data_size += bufspace;
+ if (bufspace & (data_align - 1)) {
+ data_size |= data_align - 1;
+ data_size += 1;
+ }
+
+ {
+ char data_vla_buf[(nargs + 1) * data_size + data_align];
+ libsyscalls_symbol_printer_function *funcs_vla[nargs + 1];
+
+ data = (void *)ALIGN_BUF(data_vla_buf, data_align);
+ funcs = funcs_vla;
+
+ nsyms = 0;
+ for (i = 0; i < nargs; i++) {
+ funcs[i] = get_linux_symbol_extractor_by_arg_nr(arch, syscall, i, &data[i]);
+ nsyms += !!funcs[i];
+ }
+ funcs[i] = get_linux_symbol_extractor_by_arg_nr(arch, syscall, -1, &data[i]);
+ nsyms += !!funcs[i];
+
+ (void) syscall_argument;
+ (void) syscall_number;
+
+ return build_syscall_display_info(data, data_size, data_align, funcs, syscall, nargs, nsyms);
+ }
+}