/* 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 */);
}
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
#endif
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;
}
#if defined(__clang__)
# pragma clang diagnostic pop
#endif
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 ((long long int)*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 + %llu)", (long long int)*valuep, ~*valuep / 8, *valuep & 7);
(void) fallback_out;
*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;
}
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
#endif
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(LIBSYSCALLS_SYMBOL_PRINTER_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;
}
{
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wvla"
#endif
char data_vla_buf[(size_t)(nargs + 1) * data_size + data_align];
libsyscalls_symbol_printer_function *funcs_vla[nargs + 1];
#if defined(__clang__)
# pragma clang diagnostic pop
#endif
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);
}
}
#if defined(__clang__)
# pragma clang diagnostic pop
#endif