1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * System call table mapper
4 *
5 * (C) 2016 Arnaldo Carvalho de Melo <acme@redhat.com>
6 */
7
8 #include "syscalltbl.h"
9 #include <stdlib.h>
10 #include <asm/bitsperlong.h>
11 #include <linux/compiler.h>
12 #include <linux/kernel.h>
13 #include <linux/zalloc.h>
14
15 #include <string.h>
16 #include "string2.h"
17
18 #include "trace/beauty/generated/syscalltbl.c"
19
find_table(int e_machine)20 static const struct syscalltbl *find_table(int e_machine)
21 {
22 static const struct syscalltbl *last_table;
23 static int last_table_machine = EM_NONE;
24
25 /* Tables only exist for EM_SPARC. */
26 if (e_machine == EM_SPARCV9)
27 e_machine = EM_SPARC;
28
29 if (last_table_machine == e_machine && last_table != NULL)
30 return last_table;
31
32 for (size_t i = 0; i < ARRAY_SIZE(syscalltbls); i++) {
33 const struct syscalltbl *entry = &syscalltbls[i];
34
35 if (entry->e_machine != e_machine && entry->e_machine != EM_NONE)
36 continue;
37
38 last_table = entry;
39 last_table_machine = e_machine;
40 return entry;
41 }
42 return NULL;
43 }
44
syscalltbl__name(int e_machine,int id)45 const char *syscalltbl__name(int e_machine, int id)
46 {
47 const struct syscalltbl *table = find_table(e_machine);
48
49 if (e_machine == EM_MIPS && id > 1000) {
50 /*
51 * MIPS may encode the N32/64/O32 type in the high part of
52 * syscall number. Mask this off if present. See the values of
53 * __NR_N32_Linux, __NR_64_Linux, __NR_O32_Linux and __NR_Linux.
54 */
55 id = id % 1000;
56 }
57 if (table && id >= 0 && id < table->num_to_name_len)
58 return table->num_to_name[id];
59 return NULL;
60 }
61
62 struct syscall_cmp_key {
63 const char *name;
64 const char *const *tbl;
65 };
66
syscallcmpname(const void * vkey,const void * ventry)67 static int syscallcmpname(const void *vkey, const void *ventry)
68 {
69 const struct syscall_cmp_key *key = vkey;
70 const uint16_t *entry = ventry;
71
72 return strcmp(key->name, key->tbl[*entry]);
73 }
74
syscalltbl__id(int e_machine,const char * name)75 int syscalltbl__id(int e_machine, const char *name)
76 {
77 const struct syscalltbl *table = find_table(e_machine);
78 struct syscall_cmp_key key;
79 const uint16_t *id;
80
81 if (!table)
82 return -1;
83
84 key.name = name;
85 key.tbl = table->num_to_name;
86 id = bsearch(&key, table->sorted_names, table->sorted_names_len,
87 sizeof(table->sorted_names[0]), syscallcmpname);
88
89 return id ? *id : -1;
90 }
91
syscalltbl__num_idx(int e_machine)92 int syscalltbl__num_idx(int e_machine)
93 {
94 const struct syscalltbl *table = find_table(e_machine);
95
96 if (!table)
97 return 0;
98
99 return table->sorted_names_len;
100 }
101
syscalltbl__id_at_idx(int e_machine,int idx)102 int syscalltbl__id_at_idx(int e_machine, int idx)
103 {
104 const struct syscalltbl *table = find_table(e_machine);
105
106 if (!table)
107 return -1;
108
109 assert(idx >= 0 && idx < table->sorted_names_len);
110 return table->sorted_names[idx];
111 }
112
syscalltbl__strglobmatch_next(int e_machine,const char * syscall_glob,int * idx)113 int syscalltbl__strglobmatch_next(int e_machine, const char *syscall_glob, int *idx)
114 {
115 const struct syscalltbl *table = find_table(e_machine);
116
117 for (int i = *idx + 1; table && i < table->sorted_names_len; ++i) {
118 const char *name = table->num_to_name[table->sorted_names[i]];
119
120 if (strglobmatch(name, syscall_glob)) {
121 *idx = i;
122 return table->sorted_names[i];
123 }
124 }
125
126 return -1;
127 }
128
syscalltbl__strglobmatch_first(int e_machine,const char * syscall_glob,int * idx)129 int syscalltbl__strglobmatch_first(int e_machine, const char *syscall_glob, int *idx)
130 {
131 *idx = -1;
132 return syscalltbl__strglobmatch_next(e_machine, syscall_glob, idx);
133 }
134