Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tools: Allow generating per-arch syscall table arrays

Tools should use a mechanism similar to arch/x86/entry/syscalls/ to
generate a header file with the definitions for two variables:

static const char *syscalltbl_x86_64[] = {
[0] = "read",
[1] = "write",
<SNIP>
[324] = "membarrier",
[325] = "mlock2",
[326] = "copy_file_range",
};
static const int syscalltbl_x86_64_max_id = 326;

In a per arch file that should then be included in
tools/perf/util/syscalltbl.c.

First one will be for x86_64.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/n/tip-02uuamkxgccczdth8komspgp@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

+92 -3
+88 -3
tools/perf/util/syscalltbl.c
··· 14 14 */ 15 15 16 16 #include "syscalltbl.h" 17 - #include <string.h> 18 - #include <libaudit.h> 17 + #include <stdlib.h> 19 18 19 + #ifdef HAVE_SYSCALL_TABLE 20 + #include <linux/compiler.h> 21 + #include <string.h> 22 + #include "util.h" 23 + 24 + struct syscall { 25 + int id; 26 + const char *name; 27 + }; 28 + 29 + static int syscallcmpname(const void *vkey, const void *ventry) 30 + { 31 + const char *key = vkey; 32 + const struct syscall *entry = ventry; 33 + 34 + return strcmp(key, entry->name); 35 + } 36 + 37 + static int syscallcmp(const void *va, const void *vb) 38 + { 39 + const struct syscall *a = va, *b = vb; 40 + 41 + return strcmp(a->name, b->name); 42 + } 43 + 44 + static int syscalltbl__init_native(struct syscalltbl *tbl) 45 + { 46 + int nr_entries = 0, i, j; 47 + struct syscall *entries; 48 + 49 + for (i = 0; i <= syscalltbl_native_max_id; ++i) 50 + if (syscalltbl_native[i]) 51 + ++nr_entries; 52 + 53 + entries = tbl->syscalls.entries = malloc(sizeof(struct syscall) * nr_entries); 54 + if (tbl->syscalls.entries == NULL) 55 + return -1; 56 + 57 + for (i = 0, j = 0; i <= syscalltbl_native_max_id; ++i) { 58 + if (syscalltbl_native[i]) { 59 + entries[j].name = syscalltbl_native[i]; 60 + entries[j].id = i; 61 + ++j; 62 + } 63 + } 64 + 65 + qsort(tbl->syscalls.entries, nr_entries, sizeof(struct syscall), syscallcmp); 66 + tbl->syscalls.nr_entries = nr_entries; 67 + return 0; 68 + } 20 69 21 70 struct syscalltbl *syscalltbl__new(void) 22 71 { 23 72 struct syscalltbl *tbl = malloc(sizeof(*tbl)); 24 73 if (tbl) { 25 - tbl->audit_machine = audit_detect_machine(); 74 + if (syscalltbl__init_native(tbl)) { 75 + free(tbl); 76 + return NULL; 77 + } 26 78 } 79 + return tbl; 80 + } 81 + 82 + void syscalltbl__delete(struct syscalltbl *tbl) 83 + { 84 + zfree(&tbl->syscalls.entries); 85 + free(tbl); 86 + } 87 + 88 + const char *syscalltbl__name(const struct syscalltbl *tbl __maybe_unused, int id) 89 + { 90 + return id <= syscalltbl_native_max_id ? syscalltbl_native[id]: NULL; 91 + } 92 + 93 + int syscalltbl__id(struct syscalltbl *tbl, const char *name) 94 + { 95 + struct syscall *sc = bsearch(name, tbl->syscalls.entries, 96 + tbl->syscalls.nr_entries, sizeof(*sc), 97 + syscallcmpname); 98 + 99 + return sc ? sc->id : -1; 100 + } 101 + 102 + #else /* HAVE_SYSCALL_TABLE */ 103 + 104 + #include <libaudit.h> 105 + 106 + struct syscalltbl *syscalltbl__new(void) 107 + { 108 + struct syscalltbl *tbl = malloc(sizeof(*tbl)); 109 + if (tbl) 110 + tbl->audit_machine = audit_detect_machine(); 27 111 return tbl; 28 112 } 29 113 ··· 125 41 { 126 42 return audit_name_to_syscall(name, tbl->audit_machine); 127 43 } 44 + #endif /* HAVE_SYSCALL_TABLE */
+4
tools/perf/util/syscalltbl.h
··· 4 4 struct syscalltbl { 5 5 union { 6 6 int audit_machine; 7 + struct { 8 + int nr_entries; 9 + void *entries; 10 + } syscalls; 7 11 }; 8 12 }; 9 13