xref: /freebsd/sys/tools/syscalls/scripts/systrace_args.lua (revision 42d075f4b7b74eb3c4f943d6bdcc2aeb56be6388)
1#!/usr/libexec/flua
2--
3-- SPDX-License-Identifier: BSD-2-Clause
4--
5-- Copyright (c) 2024 Tyler Baxter <agge@FreeBSD.org>
6-- Copyright (c) 2023 Warner Losh <imp@bsdimp.com>
7-- Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
8--
9
10-- Setup to be a module, or ran as its own script.
11local systrace_args = {}
12local script = not pcall(debug.getlocal, 4, 1)	-- TRUE if script.
13if script then
14	-- Add library root to the package path.
15	local path = arg[0]:gsub("/[^/]+.lua$", "")
16	package.path = package.path .. ";" .. path .. "/../?.lua"
17end
18
19local FreeBSDSyscall = require("core.freebsd-syscall")
20local util = require("tools.util")
21local generator = require("tools.generator")
22
23-- File has not been decided yet; config will decide file.  Default defined as
24-- /dev/null.
25systrace_args.file = "/dev/null"
26
27function systrace_args.generate(tbl, config, fh)
28	-- Grab the master system calls table.
29	local s = tbl.syscalls
30
31	-- Bind the generator to the parameter file.
32	local gen = generator:new({}, fh)
33	gen.storage_levels = {}	-- make sure storage is clear
34
35	-- 64-bit padding preprocessor directive.
36	gen:pad64(config.abiChanges("pair_64bit"))
37
38	-- Write the generated preamble.
39	gen:preamble(
40	    "System call argument to DTrace register array conversion.\n" ..
41	    "\n" ..
42	    "This file is part of the DTrace syscall provider.")
43
44	gen:write(string.format([[
45static void
46systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
47{
48	int64_t *iarg = (int64_t *)uarg;
49	int a = 0;
50	switch (sysnum) {
51]]))
52
53	gen:store(string.format([[
54static void
55systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
56{
57	const char *p = NULL;
58	switch (sysnum) {
59]]), 1)
60
61	gen:store(string.format([[
62static void
63systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
64{
65	const char *p = NULL;
66	switch (sysnum) {
67]]), 2)
68
69	for _, v in pairs(s) do
70
71		gen:write(v.prolog);
72		gen:store(v.prolog, 1);
73		gen:store(v.prolog, 2);
74
75		-- Handle non compat:
76		if v:native() then
77			gen:write(string.format([[
78	/* %s */
79	case %d: {
80]], v.name, v.num))
81
82			gen:store(string.format([[
83	/* %s */
84	case %d:
85]], v.name, v.num), 1)
86
87			gen:store(string.format([[
88	/* %s */
89	case %d:
90]], v.name, v.num), 2)
91
92			local n_args = #v.args
93			if v.type.SYSMUX then
94				n_args = 0
95			end
96
97			if #v.args > 0 and not v.type.SYSMUX then
98				local padding = ""
99
100				gen:write(string.format([[
101		struct %s *p = params;
102]],
103				    v.arg_alias))
104
105				gen:store([[
106		switch (ndx) {
107]],
108				    1)
109
110				for idx, arg in ipairs(v.args) do
111					local argtype = util.trim(
112						arg.type:gsub(
113						    "__restrict$", ""), nil)
114					if argtype == "int" and
115					    arg.name == "_pad" and
116					    config.abiChanges("pair_64bit") then
117						gen:store(
118						    "#ifdef PAD64_REQUIRED\n",
119						    1)
120					end
121
122					-- Pointer arg?
123					local desc
124					if argtype:find("*") then
125						desc = "userland " .. argtype
126					else
127						desc = argtype;
128					end
129
130					gen:store(string.format([[
131		case %d%s:
132			p = "%s";
133			break;
134]],
135					    idx - 1, padding, desc), 1)
136
137					if argtype == "int" and
138					    arg.name == "_pad" and
139					   config.abiChanges("pair_64bit") then
140						padding = " - _P_"
141						gen:store([[
142#define _P_ 0
143#else
144#define _P_ 1
145#endif
146]],
147					    1)
148					end
149
150					if util.isPtrType(argtype,
151					    config.abi_intptr_t) then
152						gen:write(string.format([[
153		uarg[a++] = (%s)p->%s; /* %s */
154]],
155						    config.ptr_intptr_t_cast,
156						    arg.name, argtype))
157					elseif argtype == "union l_semun" then
158						gen:write(string.format([[
159		uarg[a++] = p->%s.buf; /* %s */
160]],
161						    arg.name, argtype))
162					elseif argtype:sub(1,1) == "u" or
163					    argtype == "size_t" then
164						gen:write(string.format([[
165		uarg[a++] = p->%s; /* %s */
166]],
167						    arg.name, argtype))
168					else
169						if argtype == "int" and
170						    arg.name == "_pad" and
171						    config.abiChanges(
172						    "pair_64bit") then
173							gen:write([[
174#ifdef PAD64_REQUIRED
175]])
176						end
177
178						gen:write(string.format([[
179		iarg[a++] = p->%s; /* %s */
180]],
181						    arg.name, argtype))
182
183						if argtype == "int" and
184						    arg.name == "_pad" and
185						    config.abiChanges(
186						    "pair_64bit") then
187							gen:write("#endif\n")
188						end
189					end
190				end
191
192				gen:store([[
193		default:
194			break;
195		};
196]],
197				    1)
198
199				if padding ~= "" then
200					gen:store("#undef _P_\n\n", 1)
201				end
202
203				gen:store(string.format([[
204		if (ndx == 0 || ndx == 1)
205			p = "%s";
206		break;
207]], v.ret), 2)
208		end
209
210		gen:write(string.format("\t\t*n_args = %d;\n\t\tbreak;\n\t}\n",
211		    n_args))
212		gen:store("\t\tbreak;\n", 1)
213
214		-- Handle compat (everything >= FREEBSD3):
215		-- Do nothing, only for native.
216		end
217	end
218
219	gen:write(tbl.epilog)
220	gen:write([[
221	default:
222		*n_args = 0;
223		break;
224	};
225}
226]])
227
228	gen:store(tbl.epilog, 1)
229	gen:store([[
230	default:
231		break;
232	};
233	if (p != NULL)
234		strlcpy(desc, p, descsz);
235}
236]], 1)
237
238	gen:store(tbl.epilog, 2)
239	gen:store([[
240	default:
241		break;
242	};
243	if (p != NULL)
244		strlcpy(desc, p, descsz);
245}
246]], 2)
247
248	-- Write all stored lines.
249	if gen.storage_levels ~= nil then
250		gen:writeStorage()
251	end
252
253end
254
255-- Entry of script:
256if script then
257	local config = require("config")
258
259	if #arg < 1 or #arg > 2 then
260		error("usage: " .. arg[0] .. " syscall.master")
261	end
262
263	local sysfile, configfile = arg[1], arg[2]
264
265	config.merge(configfile)
266	config.mergeCompat()
267
268	-- The parsed system call table.
269	local tbl = FreeBSDSyscall:new{sysfile = sysfile, config = config}
270
271	systrace_args.file = config.systrace	-- change file here
272	systrace_args.generate(tbl, config, systrace_args.file)
273end
274
275-- Return the module.
276return systrace_args
277