diff options
Diffstat (limited to '')
-rw-r--r-- | tools/perf/util/syscalltbl.c | 197 |
1 files changed, 77 insertions, 120 deletions
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c index 03bd99d3be16..67a8ec10e9e4 100644 --- a/tools/perf/util/syscalltbl.c +++ b/tools/perf/util/syscalltbl.c @@ -7,170 +7,127 @@ #include "syscalltbl.h" #include <stdlib.h> +#include <asm/bitsperlong.h> #include <linux/compiler.h> +#include <linux/kernel.h> #include <linux/zalloc.h> -#ifdef HAVE_SYSCALL_TABLE_SUPPORT #include <string.h> #include "string2.h" -#if defined(__x86_64__) -#include <asm/syscalls_64.c> -const int syscalltbl_native_max_id = SYSCALLTBL_x86_64_MAX_ID; -static const char **syscalltbl_native = syscalltbl_x86_64; -#elif defined(__s390x__) -#include <asm/syscalls_64.c> -const int syscalltbl_native_max_id = SYSCALLTBL_S390_64_MAX_ID; -static const char **syscalltbl_native = syscalltbl_s390_64; -#elif defined(__powerpc64__) -#include <asm/syscalls_64.c> -const int syscalltbl_native_max_id = SYSCALLTBL_POWERPC_64_MAX_ID; -static const char **syscalltbl_native = syscalltbl_powerpc_64; -#elif defined(__powerpc__) -#include <asm/syscalls_32.c> -const int syscalltbl_native_max_id = SYSCALLTBL_POWERPC_32_MAX_ID; -static const char **syscalltbl_native = syscalltbl_powerpc_32; -#elif defined(__aarch64__) -#include <asm/syscalls.c> -const int syscalltbl_native_max_id = SYSCALLTBL_ARM64_MAX_ID; -static const char **syscalltbl_native = syscalltbl_arm64; -#endif - -struct syscall { - int id; - const char *name; -}; +#include "trace/beauty/generated/syscalltbl.c" -static int syscallcmpname(const void *vkey, const void *ventry) +static const struct syscalltbl *find_table(int e_machine) { - const char *key = vkey; - const struct syscall *entry = ventry; + static const struct syscalltbl *last_table; + static int last_table_machine = EM_NONE; - return strcmp(key, entry->name); -} + /* Tables only exist for EM_SPARC. */ + if (e_machine == EM_SPARCV9) + e_machine = EM_SPARC; -static int syscallcmp(const void *va, const void *vb) -{ - const struct syscall *a = va, *b = vb; + if (last_table_machine == e_machine && last_table != NULL) + return last_table; - return strcmp(a->name, b->name); -} + for (size_t i = 0; i < ARRAY_SIZE(syscalltbls); i++) { + const struct syscalltbl *entry = &syscalltbls[i]; -static int syscalltbl__init_native(struct syscalltbl *tbl) -{ - int nr_entries = 0, i, j; - struct syscall *entries; - - for (i = 0; i <= syscalltbl_native_max_id; ++i) - if (syscalltbl_native[i]) - ++nr_entries; + if (entry->e_machine != e_machine && entry->e_machine != EM_NONE) + continue; - entries = tbl->syscalls.entries = malloc(sizeof(struct syscall) * nr_entries); - if (tbl->syscalls.entries == NULL) - return -1; - - for (i = 0, j = 0; i <= syscalltbl_native_max_id; ++i) { - if (syscalltbl_native[i]) { - entries[j].name = syscalltbl_native[i]; - entries[j].id = i; - ++j; - } + last_table = entry; + last_table_machine = e_machine; + return entry; } - - qsort(tbl->syscalls.entries, nr_entries, sizeof(struct syscall), syscallcmp); - tbl->syscalls.nr_entries = nr_entries; - tbl->syscalls.max_id = syscalltbl_native_max_id; - return 0; + return NULL; } -struct syscalltbl *syscalltbl__new(void) +const char *syscalltbl__name(int e_machine, int id) { - struct syscalltbl *tbl = malloc(sizeof(*tbl)); - if (tbl) { - if (syscalltbl__init_native(tbl)) { - free(tbl); - return NULL; - } + const struct syscalltbl *table = find_table(e_machine); + + if (e_machine == EM_MIPS && id > 1000) { + /* + * MIPS may encode the N32/64/O32 type in the high part of + * syscall number. Mask this off if present. See the values of + * __NR_N32_Linux, __NR_64_Linux, __NR_O32_Linux and __NR_Linux. + */ + id = id % 1000; } - return tbl; + if (table && id >= 0 && id < table->num_to_name_len) + return table->num_to_name[id]; + return NULL; } -void syscalltbl__delete(struct syscalltbl *tbl) -{ - zfree(&tbl->syscalls.entries); - free(tbl); -} +struct syscall_cmp_key { + const char *name; + const char *const *tbl; +}; -const char *syscalltbl__name(const struct syscalltbl *tbl __maybe_unused, int id) +static int syscallcmpname(const void *vkey, const void *ventry) { - return id <= syscalltbl_native_max_id ? syscalltbl_native[id]: NULL; + const struct syscall_cmp_key *key = vkey; + const uint16_t *entry = ventry; + + return strcmp(key->name, key->tbl[*entry]); } -int syscalltbl__id(struct syscalltbl *tbl, const char *name) +int syscalltbl__id(int e_machine, const char *name) { - struct syscall *sc = bsearch(name, tbl->syscalls.entries, - tbl->syscalls.nr_entries, sizeof(*sc), - syscallcmpname); + const struct syscalltbl *table = find_table(e_machine); + struct syscall_cmp_key key; + const uint16_t *id; + + if (!table) + return -1; - return sc ? sc->id : -1; + key.name = name; + key.tbl = table->num_to_name; + id = bsearch(&key, table->sorted_names, table->sorted_names_len, + sizeof(table->sorted_names[0]), syscallcmpname); + + return id ? *id : -1; } -int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx) +int syscalltbl__num_idx(int e_machine) { - int i; - struct syscall *syscalls = tbl->syscalls.entries; + const struct syscalltbl *table = find_table(e_machine); - for (i = *idx + 1; i < tbl->syscalls.nr_entries; ++i) { - if (strglobmatch(syscalls[i].name, syscall_glob)) { - *idx = i; - return syscalls[i].id; - } - } + if (!table) + return 0; - return -1; + return table->sorted_names_len; } -int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx) +int syscalltbl__id_at_idx(int e_machine, int idx) { - *idx = -1; - return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx); -} - -#else /* HAVE_SYSCALL_TABLE_SUPPORT */ + const struct syscalltbl *table = find_table(e_machine); -#include <libaudit.h> + if (!table) + return -1; -struct syscalltbl *syscalltbl__new(void) -{ - struct syscalltbl *tbl = zalloc(sizeof(*tbl)); - if (tbl) - tbl->audit_machine = audit_detect_machine(); - return tbl; + assert(idx >= 0 && idx < table->sorted_names_len); + return table->sorted_names[idx]; } -void syscalltbl__delete(struct syscalltbl *tbl) +int syscalltbl__strglobmatch_next(int e_machine, const char *syscall_glob, int *idx) { - free(tbl); -} + const struct syscalltbl *table = find_table(e_machine); -const char *syscalltbl__name(const struct syscalltbl *tbl, int id) -{ - return audit_syscall_to_name(id, tbl->audit_machine); -} + for (int i = *idx + 1; table && i < table->sorted_names_len; ++i) { + const char *name = table->num_to_name[table->sorted_names[i]]; -int syscalltbl__id(struct syscalltbl *tbl, const char *name) -{ - return audit_name_to_syscall(name, tbl->audit_machine); -} + if (strglobmatch(name, syscall_glob)) { + *idx = i; + return table->sorted_names[i]; + } + } -int syscalltbl__strglobmatch_next(struct syscalltbl *tbl __maybe_unused, - const char *syscall_glob __maybe_unused, int *idx __maybe_unused) -{ return -1; } -int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx) +int syscalltbl__strglobmatch_first(int e_machine, const char *syscall_glob, int *idx) { - return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx); + *idx = -1; + return syscalltbl__strglobmatch_next(e_machine, syscall_glob, idx); } -#endif /* HAVE_SYSCALL_TABLE_SUPPORT */ |