/* 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 / 01000) & 7); digits3: data->buf[i++] = '0' | ((value / 0100) & 7); digits2: data->buf[i++] = '0' | ((value / 010) & 7); digits1: data->buf[i++] = '0' | ((value / 01) & 7); } 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) & 7); digits2: data->buf[i++] = '0' | ((value / 070) & 7); digits1: data->buf[i++] = '0' | ((value / 07) & 7); } 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); } }