Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/tools/syscalls/scripts/sysproto_h.lua
39530 views
1
#!/usr/libexec/flua
2
--
3
-- SPDX-License-Identifier: BSD-2-Clause
4
--
5
-- Copyright (c) 2024 Tyler Baxter <[email protected]>
6
-- Copyright (c) 2019 Kyle Evans <[email protected]>
7
--
8
9
-- Setup to be a module, or ran as its own script.
10
local sysproto_h = {}
11
local script = not pcall(debug.getlocal, 4, 1) -- TRUE if script.
12
if script then
13
-- Add library root to the package path.
14
local path = arg[0]:gsub("/[^/]+.lua$", "")
15
package.path = package.path .. ";" .. path .. "/../?.lua"
16
end
17
18
local FreeBSDSyscall = require("core.freebsd-syscall")
19
local generator = require("tools.generator")
20
21
-- File has not been decided yet; config will decide file. Default defined as
22
-- /dev/null.
23
sysproto_h.file = "/dev/null"
24
25
function sysproto_h.generate(tbl, config, fh)
26
-- Grab the master system calls table.
27
local s = tbl.syscalls
28
29
-- Bind the generator to the parameter file.
30
local gen = generator:new({}, fh)
31
gen.storage_levels = {} -- make sure storage is clear
32
33
-- Write the generated preamble.
34
gen:preamble("System call prototypes.")
35
36
-- Write out all the preprocessor directives.
37
gen:write(string.format([[
38
#ifndef %s
39
#define %s
40
41
#include <sys/types.h>
42
#include <sys/signal.h>
43
#include <sys/cpuset.h>
44
#include <sys/domainset.h>
45
#include <sys/_ffcounter.h>
46
#include <sys/_semaphore.h>
47
#include <sys/ucontext.h>
48
#include <sys/wait.h>
49
50
#include <bsm/audit_kevents.h>
51
52
struct proc;
53
54
struct thread;
55
56
#define PAD_(t) (sizeof(syscallarg_t) <= sizeof(t) ? \
57
0 : sizeof(syscallarg_t) - sizeof(t))
58
59
#if BYTE_ORDER == LITTLE_ENDIAN
60
#define PADL_(t) 0
61
#define PADR_(t) PAD_(t)
62
#else
63
#define PADL_(t) PAD_(t)
64
#define PADR_(t) 0
65
#endif
66
67
]], config.sysproto_h, config.sysproto_h))
68
69
-- 64-bit padding preprocessor directive.
70
gen:pad64(config.abiChanges("pair_64bit"))
71
72
--
73
-- Storing each compat entry requires storing multiple levels of file
74
-- generation; compat entries are given ranges of 10 instead to cope
75
-- with this. For example, 13 is indexed as 130; 131 is the second
76
-- storage level of 13.
77
--
78
79
-- Store all the compat #ifdef from compat_options at their zero index.
80
for _, v in pairs(config.compat_options) do
81
-- Tag an extra newline to the end, so it doesn't have to be
82
-- worried about later.
83
gen:store(string.format("\n#ifdef %s\n\n", v.definition),
84
v.compatlevel * 10)
85
end
86
87
for _, v in pairs(s) do
88
local c = v:compatLevel()
89
90
-- Audit defines are stored at an arbitrarily large number so
91
-- that they're always at the last storage level, and compat
92
-- entries can be indexed by their compat level (more
93
-- intuitive).
94
local audit_idx = 10000 -- this should do
95
96
gen:write(v.prolog)
97
gen:store(v.prolog, 1)
98
for _, w in pairs(config.compat_options) do
99
gen:store(v.prolog, w.compatlevel * 10)
100
end
101
102
-- Handle non-compat:
103
if v:native() then
104
-- All these negation conditions are because (in
105
-- general) these are cases where code for sysproto.h
106
-- is not generated.
107
if not v.type.NOARGS and not v.type.NOPROTO and
108
not v.type.NODEF then
109
if #v.args > 0 then
110
gen:write(string.format(
111
"struct %s {\n", v.arg_alias))
112
for _, arg in ipairs(v.args) do
113
if arg.type == "int" and
114
arg.name == "_pad" and
115
config.abiChanges(
116
"pair_64bit") then
117
gen:write("#ifdef PAD64_REQUIRED\n")
118
end
119
120
gen:write(string.format([[
121
char %s_l_[PADL_(%s)]; %s %s; char %s_r_[PADR_(%s)];
122
]],
123
arg.name, arg.type,
124
arg.type, arg.name,
125
arg.name, arg.type))
126
127
if arg.type == "int" and
128
arg.name == "_pad" and
129
config.abiChanges(
130
"pair_64bit") then
131
gen:write("#endif\n")
132
end
133
end
134
gen:write("};\n")
135
else
136
gen:write(string.format(
137
"struct %s {\n\tsyscallarg_t dummy;\n};\n",
138
v.arg_alias))
139
end
140
end
141
if not v.type.NOPROTO and not v.type.NODEF then
142
local sys_prefix = "sys_"
143
if v.name == "nosys" or v.name == "lkmnosys" or
144
v.name == "sysarch" or
145
v.name:find("^freebsd") or
146
v.name:find("^linux") then
147
sys_prefix = ""
148
end
149
gen:store(string.format(
150
"%s\t%s%s(struct thread *, struct %s *);\n",
151
v.rettype, sys_prefix, v.name, v.arg_alias),
152
1)
153
gen:store(string.format(
154
"#define\t%sAUE_%s\t%s\n",
155
config.syscallprefix, v:symbol(), v.audit),
156
audit_idx)
157
end
158
159
-- Handle compat (everything >= FREEBSD3):
160
elseif c >= 3 then
161
local idx = c * 10
162
if not v.type.NOARGS and not v.type.NOPROTO and
163
not v.type.NODEF then
164
if #v.args > 0 then
165
gen:store(string.format(
166
"struct %s {\n", v.arg_alias), idx)
167
for _, arg in ipairs(v.args) do
168
gen:store(string.format([[
169
char %s_l_[PADL_(%s)]; %s %s; char %s_r_[PADR_(%s)];
170
]],
171
arg.name, arg.type,
172
arg.type, arg.name,
173
arg.name, arg.type), idx)
174
end
175
gen:store("};\n", idx)
176
else
177
-- Not stored, written on the first run.
178
gen:write(string.format([[
179
struct %s {
180
syscallarg_t dummy;
181
};
182
]],
183
v.arg_alias))
184
end
185
end
186
if not v.type.NOPROTO and not v.type.NODEF then
187
gen:store(string.format([[
188
%s %s%s(struct thread *, struct %s *);
189
]],
190
v.rettype, v:compatPrefix(), v.name,
191
v.arg_alias), idx + 1)
192
gen:store(string.format([[
193
#define %sAUE_%s%s %s
194
]],
195
config.syscallprefix, v:compatPrefix(),
196
v.name, v.audit), audit_idx)
197
end
198
end
199
-- Do nothing for obsolete, unimplemented, and reserved.
200
end
201
202
-- Append #endif to the end of each compat option.
203
for _, v in pairs(config.compat_options) do
204
-- Based on how they're indexed, 9 is the last index.
205
local end_idx = (v.compatlevel * 10) + 9
206
-- Need an extra newline after #endif.
207
gen:store(string.format("\n#endif /* %s */\n\n", v.definition),
208
end_idx)
209
end
210
211
gen:write(tbl.epilog)
212
gen:store(tbl.epilog, 1)
213
for _, w in pairs(config.compat_options) do
214
gen:store(tbl.epilog, w.compatlevel * 10)
215
end
216
217
if gen.storage_levels ~= nil then
218
gen:writeStorage()
219
end
220
221
-- After storage has been unrolled, tag on the ending bits.
222
gen:write(string.format([[
223
224
#undef PAD_
225
#undef PADL_
226
#undef PADR_
227
228
#endif /* !%s */
229
]], config.sysproto_h))
230
end
231
232
-- Entry of script:
233
if script then
234
local config = require("config")
235
236
if #arg < 1 or #arg > 2 then
237
error("usage: " .. arg[0] .. " syscall.master")
238
end
239
240
local sysfile, configfile = arg[1], arg[2]
241
242
config.merge(configfile)
243
config.mergeCompat()
244
245
-- The parsed system call table.
246
local tbl = FreeBSDSyscall:new{sysfile = sysfile, config = config}
247
248
sysproto_h.file = config.sysproto -- change file here
249
sysproto_h.generate(tbl, config, sysproto_h.file)
250
end
251
252
-- Return the module.
253
return sysproto_h
254
255