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